blob: dae9cedb0521c54a1888a73421e0a92d537ce1a6 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/*========================================================================
43
44 \file wlan_hdd_main.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
54/**=========================================================================
55
56 EDIT HISTORY FOR FILE
57
58
59 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
61
62
63 $Header:$ $DateTime: $ $Author: $
64
65
66 when who what, where, why
67 -------- --- --------------------------------------------------------
68 04/5/09 Shailender Created module.
69 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
70 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
71 ==========================================================================*/
72
73/*--------------------------------------------------------------------------
74 Include Files
75 ------------------------------------------------------------------------*/
76//#include <wlan_qct_driver.h>
77#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070078#include <vos_api.h>
79#include <vos_sched.h>
80#include <vos_power.h>
81#include <linux/etherdevice.h>
82#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070083#ifdef ANI_BUS_TYPE_PLATFORM
84#include <linux/wcnss_wlan.h>
85#endif //ANI_BUS_TYPE_PLATFORM
86#ifdef ANI_BUS_TYPE_PCI
87#include "wcnss_wlan.h"
88#endif /* ANI_BUS_TYPE_PCI */
89#include <wlan_hdd_tx_rx.h>
90#include <palTimer.h>
91#include <wniApi.h>
92#include <wlan_nlink_srv.h>
93#include <wlan_btc_svc.h>
94#include <wlan_hdd_cfg.h>
95#include <wlan_ptt_sock_svc.h>
96#include <wlan_hdd_wowl.h>
97#include <wlan_hdd_misc.h>
98#include <wlan_hdd_wext.h>
99#ifdef WLAN_BTAMP_FEATURE
100#include <bap_hdd_main.h>
101#include <bapInternal.h>
102#endif // WLAN_BTAMP_FEATURE
103
Jeff Johnson295189b2012-06-20 16:38:30 -0700104#include <linux/wireless.h>
105#include <net/cfg80211.h>
106#include "wlan_hdd_cfg80211.h"
107#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700108#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700109int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include "sapApi.h"
111#include <linux/semaphore.h>
112#include <mach/subsystem_restart.h>
113#include <wlan_hdd_hostapd.h>
114#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700115#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700116#include "wlan_hdd_dev_pwr.h"
117#ifdef WLAN_BTAMP_FEATURE
118#include "bap_hdd_misc.h"
119#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700120#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700121#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800122#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530123#ifdef FEATURE_WLAN_TDLS
124#include "wlan_hdd_tdls.h"
125#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700126
127#ifdef MODULE
128#define WLAN_MODULE_NAME module_name(THIS_MODULE)
129#else
130#define WLAN_MODULE_NAME "wlan"
131#endif
132
133#ifdef TIMER_MANAGER
134#define TIMER_MANAGER_STR " +TIMER_MANAGER"
135#else
136#define TIMER_MANAGER_STR ""
137#endif
138
139#ifdef MEMORY_DEBUG
140#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
141#else
142#define MEMORY_DEBUG_STR ""
143#endif
144
145/* the Android framework expects this param even though we don't use it */
146#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700147static char fwpath_buffer[BUF_LEN];
148static struct kparam_string fwpath = {
149 .string = fwpath_buffer,
150 .maxlen = BUF_LEN,
151};
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700152#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700153static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700154#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700155
Jeff Johnsone7245742012-09-05 17:12:55 -0700156/*
157 * The rate at which the driver sends RESTART event to supplicant
158 * once the function 'vos_wlanRestart()' is called
159 *
160 */
161#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
162#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700163
164/*
165 * Size of Driver command strings from upper layer
166 */
167#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
168#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
169
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800170#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700171static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700172#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700173/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700174static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700175
176//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700177static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
178static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
179static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
180void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800181void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700182
Jeff Johnson295189b2012-06-20 16:38:30 -0700183v_U16_t hdd_select_queue(struct net_device *dev,
184 struct sk_buff *skb);
185
186#ifdef WLAN_FEATURE_PACKET_FILTERING
187static void hdd_set_multicast_list(struct net_device *dev);
188#endif
189
190void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700191int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700192
193extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800194#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
195void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
196static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
197static VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700198static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
199 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
200 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700201static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
202 tANI_U8 *pTargetApBssid,
203 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800204#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700205static int hdd_netdev_notifier_call(struct notifier_block * nb,
206 unsigned long state,
207 void *ndev)
208{
209 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700210 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700211 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700212#ifdef WLAN_BTAMP_FEATURE
213 VOS_STATUS status;
214 hdd_context_t *pHddCtx;
215#endif
216
217 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700218 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700219 (strncmp(dev->name, "p2p", 3)))
220 return NOTIFY_DONE;
221
222 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700223 return NOTIFY_DONE;
224
Jeff Johnson295189b2012-06-20 16:38:30 -0700225 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700226 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700227
Jeff Johnson27cee452013-03-27 11:10:24 -0700228 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700229 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800230 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700231 VOS_ASSERT(0);
232 return NOTIFY_DONE;
233 }
234
Jeff Johnson27cee452013-03-27 11:10:24 -0700235 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
236 if (NULL == pHddCtx)
237 {
238 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
239 VOS_ASSERT(0);
240 return NOTIFY_DONE;
241 }
242
243 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
244 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700245
246 switch (state) {
247 case NETDEV_REGISTER:
248 break;
249
250 case NETDEV_UNREGISTER:
251 break;
252
253 case NETDEV_UP:
254 break;
255
256 case NETDEV_DOWN:
257 break;
258
259 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700260 if(TRUE == pAdapter->isLinkUpSvcNeeded)
261 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700262 break;
263
264 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700265 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700266 {
267 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800268 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700269 hdd_abort_mac_scan(pAdapter->pHddCtx);
270 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800271 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700272 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
273 if(!result)
274 {
275 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800276 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700277 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700278 }
279 }
280 else
281 {
282 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700283 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700284 }
285#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700286 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700287 status = WLANBAP_StopAmp();
288 if(VOS_STATUS_SUCCESS != status )
289 {
290 pHddCtx->isAmpAllowed = VOS_TRUE;
291 hddLog(VOS_TRACE_LEVEL_FATAL,
292 "%s: Failed to stop AMP", __func__);
293 }
294 else
295 {
296 //a state m/c implementation in PAL is TBD to avoid this delay
297 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700298 if ( pHddCtx->isAmpAllowed )
299 {
300 WLANBAP_DeregisterFromHCI();
301 pHddCtx->isAmpAllowed = VOS_FALSE;
302 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700303 }
304#endif //WLAN_BTAMP_FEATURE
305 break;
306
307 default:
308 break;
309 }
310
311 return NOTIFY_DONE;
312}
313
314struct notifier_block hdd_netdev_notifier = {
315 .notifier_call = hdd_netdev_notifier_call,
316};
317
318/*---------------------------------------------------------------------------
319 * Function definitions
320 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700321void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
322void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700323//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700324static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700325#ifndef MODULE
326/* current con_mode - used only for statically linked driver
327 * con_mode is changed by userspace to indicate a mode change which will
328 * result in calling the module exit and init functions. The module
329 * exit function will clean up based on the value of con_mode prior to it
330 * being changed by userspace. So curr_con_mode records the current con_mode
331 * for exit when con_mode becomes the next mode for init
332 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700333static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700334#endif
335
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800336/**---------------------------------------------------------------------------
337
338 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
339
340 Called immediately after the cfg.ini is read in order to configure
341 the desired trace levels.
342
343 \param - moduleId - module whose trace level is being configured
344 \param - bitmask - bitmask of log levels to be enabled
345
346 \return - void
347
348 --------------------------------------------------------------------------*/
349static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
350{
351 wpt_tracelevel level;
352
353 /* if the bitmask is the default value, then a bitmask was not
354 specified in cfg.ini, so leave the logging level alone (it
355 will remain at the "compiled in" default value) */
356 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
357 {
358 return;
359 }
360
361 /* a mask was specified. start by disabling all logging */
362 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
363
364 /* now cycle through the bitmask until all "set" bits are serviced */
365 level = VOS_TRACE_LEVEL_FATAL;
366 while (0 != bitmask)
367 {
368 if (bitmask & 1)
369 {
370 vos_trace_setValue(moduleId, level, 1);
371 }
372 level++;
373 bitmask >>= 1;
374 }
375}
376
377
Jeff Johnson295189b2012-06-20 16:38:30 -0700378/**---------------------------------------------------------------------------
379
380 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
381
382 Called immediately after the cfg.ini is read in order to configure
383 the desired trace levels in the WDI.
384
385 \param - moduleId - module whose trace level is being configured
386 \param - bitmask - bitmask of log levels to be enabled
387
388 \return - void
389
390 --------------------------------------------------------------------------*/
391static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
392{
393 wpt_tracelevel level;
394
395 /* if the bitmask is the default value, then a bitmask was not
396 specified in cfg.ini, so leave the logging level alone (it
397 will remain at the "compiled in" default value) */
398 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
399 {
400 return;
401 }
402
403 /* a mask was specified. start by disabling all logging */
404 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
405
406 /* now cycle through the bitmask until all "set" bits are serviced */
407 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
408 while (0 != bitmask)
409 {
410 if (bitmask & 1)
411 {
412 wpalTraceSetLevel(moduleId, level, 1);
413 }
414 level++;
415 bitmask >>= 1;
416 }
417}
Jeff Johnson295189b2012-06-20 16:38:30 -0700418
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530419/*
420 * FUNCTION: wlan_hdd_validate_context
421 * This function is used to check the HDD context
422 */
423int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
424{
425 ENTER();
426
427 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
428 {
429 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
430 "%s: HDD context is Null", __func__);
431 return -ENODEV;
432 }
433
434 if (pHddCtx->isLogpInProgress)
435 {
436 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
437 "%s: LOGP in Progress. Ignore!!!", __func__);
438 return -EAGAIN;
439 }
440
441 if (pHddCtx->isLoadUnloadInProgress)
442 {
443 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
444 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
445 return -EAGAIN;
446 }
447 return 0;
448}
449
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530450void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
451{
452 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
453 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
454 hdd_config_t *cfg_param;
455 eCsrPhyMode phyMode;
456
457 if (NULL == pHddCtx)
458 {
459 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
460 "HDD Context is null !!");
461 return ;
462 }
463
464 cfg_param = pHddCtx->cfg_ini;
465
466 if (NULL == cfg_param)
467 {
468 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
469 "cfg_params not available !!");
470 return ;
471 }
472
473 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
474
475 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
476 {
477 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
478 (eCSR_DOT11_MODE_11ac == phyMode) ||
479 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
480 {
481 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
482 "Setting phymode to 11n!!");
483 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
484 }
485 }
486 else
487 {
488 /*New country Supports 11ac as well resetting value back from .ini*/
489 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
490 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
491 return ;
492 }
493
494 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
495 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
496 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
497 {
498 VOS_STATUS vosStatus;
499
500 // need to issue a disconnect to CSR.
501 INIT_COMPLETION(pAdapter->disconnect_comp_var);
502 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
503 pAdapter->sessionId,
504 eCSR_DISCONNECT_REASON_UNSPECIFIED );
505
506 if (VOS_STATUS_SUCCESS == vosStatus)
507 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
508 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
509
510 }
511}
512
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700513void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
514{
515 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
516 hdd_config_t *cfg_param;
517
518 if (NULL == pHddCtx)
519 {
520 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
521 "HDD Context is null !!");
522 return ;
523 }
524
525 cfg_param = pHddCtx->cfg_ini;
526
527 if (NULL == cfg_param)
528 {
529 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
530 "cfg_params not available !!");
531 return ;
532 }
533
534 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
535 {
536 /*New country doesn't support DFS */
537 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
538 }
539 else
540 {
541 /*New country Supports DFS as well resetting value back from .ini*/
542 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
543 }
544
545}
546
Jeff Johnson295189b2012-06-20 16:38:30 -0700547int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
548{
549 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
550 hdd_priv_data_t priv_data;
551 tANI_U8 *command = NULL;
552 int ret = 0;
553
554 if (NULL == pAdapter)
555 {
556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700557 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700558 ret = -ENODEV;
559 goto exit;
560 }
561
Jeff Johnsone7245742012-09-05 17:12:55 -0700562 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700563 {
564 ret = -EINVAL;
565 goto exit;
566 }
567
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -0700568 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
569 {
570 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
571 "%s:LOGP in Progress. Ignore!!!", __func__);
572 ret = -EBUSY;
573 goto exit;
574 }
575
Jeff Johnson295189b2012-06-20 16:38:30 -0700576 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
577 {
578 ret = -EFAULT;
579 goto exit;
580 }
581
582 command = kmalloc(priv_data.total_len, GFP_KERNEL);
583 if (!command)
584 {
585 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700586 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700587 ret = -ENOMEM;
588 goto exit;
589 }
590
591 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
592 {
593 ret = -EFAULT;
594 goto exit;
595 }
596
597 if ((SIOCDEVPRIVATE + 1) == cmd)
598 {
599 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
600
601 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700602 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700603
604 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
605 {
606 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
607 sizeof(tSirMacAddr)))
608 {
609 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700610 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700611 ret = -EFAULT;
612 }
613 }
Amar Singhal0974e402013-02-12 14:27:46 -0800614 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700615 {
Amar Singhal0974e402013-02-12 14:27:46 -0800616 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700617 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800618
Jeff Johnson295189b2012-06-20 16:38:30 -0700619 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800620
621 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700622 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700623 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800624 "%s: SetBandCommand Info comm %s UL %d, TL %d", __func__, command, priv_data.used_len, priv_data.total_len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700625 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800626 ret = hdd_setBand_helper(dev, ptr);
627 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700628 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
629 {
630 char *country_code;
631
632 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700633
634 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530635 hdd_checkandupdate_phymode(pAdapter, country_code);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700636 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
Gopichand Nakkalaacd94112013-05-29 21:37:47 +0530637 pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700638 if( 0 != ret )
639 {
640 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
641 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
642
643 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700644 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800645#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
646 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
647 {
648 tANI_U8 *value = command;
649 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
650 tANI_U8 revision = 0;
651 eHalStatus status = eHAL_STATUS_SUCCESS;
652 v_REGDOMAIN_t regId;
653
654 status = hdd_parse_countryrev(value, countryCode, &revision);
655 if (eHAL_STATUS_SUCCESS != status)
656 {
657 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
658 "%s: Failed to parse country revision information", __func__);
659 ret = -EINVAL;
660 goto exit;
661 }
662
663 /* Validate country code */
664 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
665 if (eHAL_STATUS_SUCCESS != status)
666 {
667 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
668 "%s: Invalid country code %s", __func__, countryCode);
669 ret = -EINVAL;
670 goto exit;
671 }
672
673 /* Validate revision */
674 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
675 {
676 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
677 "%s: Invalid revision %d", __func__, revision);
678 ret = -EINVAL;
679 goto exit;
680 }
681
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700682 hdd_checkandupdate_dfssetting(pAdapter, countryCode);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530683 hdd_checkandupdate_phymode(pAdapter, countryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800684 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
Gopichand Nakkalaacd94112013-05-29 21:37:47 +0530685 pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800686 if (0 != ret)
687 {
688 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
689 "%s: SME Change Country code fail ret=%d", __func__, ret);
690 ret = -EINVAL;
691 goto exit;
692 }
693
694 if (0 == strncmp(countryCode, "KR", 2))
695 {
696 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
697 revision);
698 if (eHAL_STATUS_SUCCESS != status)
699 {
700 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
701 "%s: Failed to build valid channel list", __func__);
702 ret = -EINVAL;
703 goto exit;
704 }
705 }
706 }
707#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700708 /*
709 command should be a string having format
710 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
711 */
Amar Singhal0974e402013-02-12 14:27:46 -0800712 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700713 {
Amar Singhal0974e402013-02-12 14:27:46 -0800714 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700715
716 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700717 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700718
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800719 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700720 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800721 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
722 {
723 int suspend = 0;
724 tANI_U8 *ptr = (tANI_U8*)command + 15;
725
726 suspend = *ptr - '0';
727 hdd_set_wlan_suspend_mode(suspend);
728 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800729#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
730 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
731 {
732 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700733 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800734 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
735 eHalStatus status = eHAL_STATUS_SUCCESS;
736
737 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
738 value = value + 15;
739
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700740 /* Convert the value from ascii to integer */
741 ret = kstrtos8(value, 10, &rssi);
742 if (ret < 0)
743 {
744 /* If the input value is greater than max value of datatype, then also
745 kstrtou8 fails */
746 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
747 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
748 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
749 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
750 ret = -EINVAL;
751 goto exit;
752 }
753
Srinivas Girigowdade697412013-02-14 16:31:48 -0800754 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700755
Srinivas Girigowdade697412013-02-14 16:31:48 -0800756 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
757 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
758 {
759 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
760 "Neighbor lookup threshold value %d is out of range"
761 " (Min: %d Max: %d)", lookUpThreshold,
762 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
763 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
764 ret = -EINVAL;
765 goto exit;
766 }
767
768 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
769 "%s: Received Command to Set Roam trigger"
770 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
771
772 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
773 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
774 if (eHAL_STATUS_SUCCESS != status)
775 {
776 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
777 "%s: Failed to set roam trigger, try again", __func__);
778 ret = -EPERM;
779 goto exit;
780 }
781
782 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
783 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
784 }
785 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
786 {
787 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
788 int rssi = (-1) * lookUpThreshold;
789 char extra[32];
790 tANI_U8 len = 0;
791
792 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
793 if (copy_to_user(priv_data.buf, &extra, len + 1))
794 {
795 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
796 "%s: failed to copy data to user buffer", __func__);
797 ret = -EFAULT;
798 goto exit;
799 }
800 }
801 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
802 {
803 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700804 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700805 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700806
Srinivas Girigowdade697412013-02-14 16:31:48 -0800807 /* input refresh period is in terms of seconds */
808 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
809 value = value + 18;
810 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700811 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800812 if (ret < 0)
813 {
814 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700815 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800816 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700817 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -0800818 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700819 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
820 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800821 ret = -EINVAL;
822 goto exit;
823 }
824
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700825 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
826 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800827 {
828 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700829 "Roam scan period value %d is out of range"
830 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700831 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
832 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800833 ret = -EINVAL;
834 goto exit;
835 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700836 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800837
838 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
839 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700840 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800841
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700842 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
843 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800844 }
845 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
846 {
847 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
848 char extra[32];
849 tANI_U8 len = 0;
850
851 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
852 /* Returned value is in units of seconds */
853 if (copy_to_user(priv_data.buf, &extra, len + 1))
854 {
855 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
856 "%s: failed to copy data to user buffer", __func__);
857 ret = -EFAULT;
858 goto exit;
859 }
860 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700861 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
862 {
863 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700864 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700865 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700866
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700867 /* input refresh period is in terms of seconds */
868 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
869 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700870
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700871 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700872 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700873 if (ret < 0)
874 {
875 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700876 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700877 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700878 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700879 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700880 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
881 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
882 ret = -EINVAL;
883 goto exit;
884 }
885
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700886 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
887 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
888 {
889 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
890 "Neighbor scan results refresh period value %d is out of range"
891 " (Min: %d Max: %d)", roamScanRefreshPeriod,
892 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
893 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
894 ret = -EINVAL;
895 goto exit;
896 }
897 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
898
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
900 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700901 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700902
903 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
904 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
905 }
906 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
907 {
908 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
909 char extra[32];
910 tANI_U8 len = 0;
911
912 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
913 /* Returned value is in units of seconds */
914 if (copy_to_user(priv_data.buf, &extra, len + 1))
915 {
916 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
917 "%s: failed to copy data to user buffer", __func__);
918 ret = -EFAULT;
919 goto exit;
920 }
921 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700922#ifdef FEATURE_WLAN_LFR
923 /* SETROAMMODE */
924 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
925 {
926 tANI_U8 *value = command;
927 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
928
929 /* Move pointer to ahead of SETROAMMODE<delimiter> */
930 value = value + SIZE_OF_SETROAMMODE + 1;
931
932 /* Convert the value from ascii to integer */
933 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
934 if (ret < 0)
935 {
936 /* If the input value is greater than max value of datatype, then also
937 kstrtou8 fails */
938 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
939 "%s: kstrtou8 failed range [%d - %d]", __func__,
940 CFG_LFR_FEATURE_ENABLED_MIN,
941 CFG_LFR_FEATURE_ENABLED_MAX);
942 ret = -EINVAL;
943 goto exit;
944 }
945 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
946 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
947 {
948 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
949 "Roam Mode value %d is out of range"
950 " (Min: %d Max: %d)", roamMode,
951 CFG_LFR_FEATURE_ENABLED_MIN,
952 CFG_LFR_FEATURE_ENABLED_MAX);
953 ret = -EINVAL;
954 goto exit;
955 }
956
957 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
958 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
959 /*
960 * Note that
961 * SETROAMMODE 0 is to enable LFR while
962 * SETROAMMODE 1 is to disable LFR, but
963 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
964 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
965 */
966 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
967 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
968 else
969 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
970
971 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
972 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
973 }
974 /* GETROAMMODE */
975 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
976 {
977 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
978 char extra[32];
979 tANI_U8 len = 0;
980
981 /*
982 * roamMode value shall be inverted because the sementics is different.
983 */
984 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
985 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
986 else
987 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
988
989 len = snprintf(extra, sizeof(extra), "%s %d", command, roamMode);
990 if (copy_to_user(priv_data.buf, &extra, len + 1))
991 {
992 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
993 "%s: failed to copy data to user buffer", __func__);
994 ret = -EFAULT;
995 goto exit;
996 }
997 }
998#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -0800999#endif
1000#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1001 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
1002 {
1003 tANI_U8 *value = command;
1004 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
1005
1006 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
1007 value = value + 13;
1008 /* Convert the value from ascii to integer */
1009 ret = kstrtou8(value, 10, &roamRssiDiff);
1010 if (ret < 0)
1011 {
1012 /* If the input value is greater than max value of datatype, then also
1013 kstrtou8 fails */
1014 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1015 "%s: kstrtou8 failed range [%d - %d]", __func__,
1016 CFG_ROAM_RSSI_DIFF_MIN,
1017 CFG_ROAM_RSSI_DIFF_MAX);
1018 ret = -EINVAL;
1019 goto exit;
1020 }
1021
1022 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
1023 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
1024 {
1025 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1026 "Roam rssi diff value %d is out of range"
1027 " (Min: %d Max: %d)", roamRssiDiff,
1028 CFG_ROAM_RSSI_DIFF_MIN,
1029 CFG_ROAM_RSSI_DIFF_MAX);
1030 ret = -EINVAL;
1031 goto exit;
1032 }
1033
1034 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1035 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
1036
1037 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
1038 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
1039 }
1040 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
1041 {
1042 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
1043 char extra[32];
1044 tANI_U8 len = 0;
1045
1046 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
1047 if (copy_to_user(priv_data.buf, &extra, len + 1))
1048 {
1049 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1050 "%s: failed to copy data to user buffer", __func__);
1051 ret = -EFAULT;
1052 goto exit;
1053 }
1054 }
1055#endif
1056#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1057 else if (strncmp(command, "GETBAND", 7) == 0)
1058 {
1059 int band = -1;
1060 char extra[32];
1061 tANI_U8 len = 0;
1062 hdd_getBand_helper(pHddCtx, &band);
1063
1064 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
1065 if (copy_to_user(priv_data.buf, &extra, len + 1))
1066 {
1067 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1068 "%s: failed to copy data to user buffer", __func__);
1069 ret = -EFAULT;
1070 goto exit;
1071 }
1072 }
1073 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
1074 {
1075 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
1076 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
1077 tANI_U8 revision = 0;
1078 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
1079 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
1080 char extra[32] = {0};
1081 tANI_U8 len = 0;
1082
1083 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
1084 {
1085 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1086 "%s: failed to get country code", __func__);
1087 ret = -EFAULT;
1088 goto exit;
1089 }
1090 pBuf[uBufLen] = '\0';
1091 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
1092
1093 if (0 == strncmp(pBuf, "KR", 2))
1094 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
1095 else
1096 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
1097
1098 if (copy_to_user(priv_data.buf, &extra, len + 1))
1099 {
1100 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1101 "%s: failed to copy data to user buffer", __func__);
1102 ret = -EFAULT;
1103 goto exit;
1104 }
1105 }
1106 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1107 {
1108 tANI_U8 *value = command;
1109 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1110 tANI_U8 numChannels = 0;
1111 eHalStatus status = eHAL_STATUS_SUCCESS;
1112
1113 status = hdd_parse_channellist(value, ChannelList, &numChannels);
1114 if (eHAL_STATUS_SUCCESS != status)
1115 {
1116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1117 "%s: Failed to parse channel list information", __func__);
1118 ret = -EINVAL;
1119 goto exit;
1120 }
1121
1122 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
1123 {
1124 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1125 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
1126 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
1127 ret = -EINVAL;
1128 goto exit;
1129 }
1130 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
1131 numChannels);
1132 if (eHAL_STATUS_SUCCESS != status)
1133 {
1134 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1135 "%s: Failed to update channel list information", __func__);
1136 ret = -EINVAL;
1137 goto exit;
1138 }
1139 }
1140 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
1141 {
1142 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1143 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07001144 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001145 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07001146 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001147
1148 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
1149 ChannelList, &numChannels ))
1150 {
1151 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1152 "%s: failed to get roam scan channel list", __func__);
1153 ret = -EFAULT;
1154 goto exit;
1155 }
1156 /* output channel list is of the format
1157 [Number of roam scan channels][Channel1][Channel2]... */
1158 /* copy the number of channels in the 0th index */
1159 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
1160 for (j = 0; (j < numChannels); j++)
1161 {
1162 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
1163 }
1164
1165 if (copy_to_user(priv_data.buf, &extra, len + 1))
1166 {
1167 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1168 "%s: failed to copy data to user buffer", __func__);
1169 ret = -EFAULT;
1170 goto exit;
1171 }
1172 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001173 else if (strncmp(command, "GETCCXMODE", 10) == 0)
1174 {
1175 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1176 char extra[32];
1177 tANI_U8 len = 0;
1178
1179 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
1180 if (copy_to_user(priv_data.buf, &extra, len + 1))
1181 {
1182 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1183 "%s: failed to copy data to user buffer", __func__);
1184 ret = -EFAULT;
1185 goto exit;
1186 }
1187 }
1188 else if (strncmp(command, "GETOKCMODE", 10) == 0)
1189 {
1190 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
1191 char extra[32];
1192 tANI_U8 len = 0;
1193
1194 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
1195 if (copy_to_user(priv_data.buf, &extra, len + 1))
1196 {
1197 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1198 "%s: failed to copy data to user buffer", __func__);
1199 ret = -EFAULT;
1200 goto exit;
1201 }
1202 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001203 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001204 {
1205 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1206 char extra[32];
1207 tANI_U8 len = 0;
1208
1209 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
1210 if (copy_to_user(priv_data.buf, &extra, len + 1))
1211 {
1212 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1213 "%s: failed to copy data to user buffer", __func__);
1214 ret = -EFAULT;
1215 goto exit;
1216 }
1217 }
1218 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
1219 {
1220 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1221 char extra[32];
1222 tANI_U8 len = 0;
1223
1224 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
1225 if (copy_to_user(priv_data.buf, &extra, len + 1))
1226 {
1227 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1228 "%s: failed to copy data to user buffer", __func__);
1229 ret = -EFAULT;
1230 goto exit;
1231 }
1232 }
1233 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
1234 {
1235 tANI_U8 *value = command;
1236 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1237
1238 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1239 value = value + 26;
1240 /* Convert the value from ascii to integer */
1241 ret = kstrtou8(value, 10, &minTime);
1242 if (ret < 0)
1243 {
1244 /* If the input value is greater than max value of datatype, then also
1245 kstrtou8 fails */
1246 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1247 "%s: kstrtou8 failed range [%d - %d]", __func__,
1248 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1249 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1250 ret = -EINVAL;
1251 goto exit;
1252 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001253 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1254 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1255 {
1256 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1257 "scan min channel time value %d is out of range"
1258 " (Min: %d Max: %d)", minTime,
1259 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1260 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1261 ret = -EINVAL;
1262 goto exit;
1263 }
1264
1265 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1266 "%s: Received Command to change channel min time = %d", __func__, minTime);
1267
1268 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1269 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1270 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001271 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1272 {
1273 tANI_U8 *value = command;
1274 tANI_U8 channel = 0;
1275 tANI_U8 dwellTime = 0;
1276 tANI_U8 bufLen = 0;
1277 tANI_U8 *buf = NULL;
1278 tSirMacAddr targetApBssid;
1279 eHalStatus status = eHAL_STATUS_SUCCESS;
1280 struct ieee80211_channel chan;
1281 tANI_U8 finalLen = 0;
1282 tANI_U8 *finalBuf = NULL;
1283 tANI_U8 temp = 0;
1284 u64 cookie;
1285 hdd_station_ctx_t *pHddStaCtx = NULL;
1286 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1287
1288 /* if not associated, no need to send action frame */
1289 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1290 {
1291 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1292 ret = -EINVAL;
1293 goto exit;
1294 }
1295
1296 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1297 &dwellTime, &buf, &bufLen);
1298 if (eHAL_STATUS_SUCCESS != status)
1299 {
1300 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1301 "%s: Failed to parse send action frame data", __func__);
1302 ret = -EINVAL;
1303 goto exit;
1304 }
1305
1306 /* if the target bssid is different from currently associated AP,
1307 then no need to send action frame */
1308 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1309 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1310 {
1311 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1312 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001313 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001314 goto exit;
1315 }
1316
1317 /* if the channel number is different from operating channel then
1318 no need to send action frame */
1319 if (channel != pHddStaCtx->conn_info.operationChannel)
1320 {
1321 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1322 "%s: channel(%d) is different from operating channel(%d)",
1323 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1324 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001325 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001326 goto exit;
1327 }
1328 chan.center_freq = sme_ChnToFreq(channel);
1329
1330 finalLen = bufLen + 24;
1331 finalBuf = vos_mem_malloc(finalLen);
1332 if (NULL == finalBuf)
1333 {
1334 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1335 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001336 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001337 goto exit;
1338 }
1339 vos_mem_zero(finalBuf, finalLen);
1340
1341 /* Fill subtype */
1342 temp = SIR_MAC_MGMT_ACTION << 4;
1343 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1344
1345 /* Fill type */
1346 temp = SIR_MAC_MGMT_FRAME;
1347 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1348
1349 /* Fill destination address (bssid of the AP) */
1350 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1351
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001352 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001353 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1354
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001355 /* Fill BSSID (AP mac address) */
1356 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001357
1358 /* Fill received buffer from 24th address */
1359 vos_mem_copy(finalBuf + 24, buf, bufLen);
1360
Jeff Johnson11c33152013-04-16 17:52:40 -07001361 /* done with the parsed buffer */
1362 vos_mem_free(buf);
1363
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001364 wlan_hdd_action( NULL, dev, &chan, 0, NL80211_CHAN_HT20,
1365 1, dwellTime, finalBuf, finalLen, 1,
1366 1, &cookie );
1367 vos_mem_free(finalBuf);
1368 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001369 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1370 {
1371 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1372 char extra[32];
1373 tANI_U8 len = 0;
1374
1375 /* value is interms of msec */
1376 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1377 if (copy_to_user(priv_data.buf, &extra, len + 1))
1378 {
1379 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1380 "%s: failed to copy data to user buffer", __func__);
1381 ret = -EFAULT;
1382 goto exit;
1383 }
1384 }
1385 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1386 {
1387 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001388 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001389 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001390
1391 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1392 value = value + 19;
1393 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001394 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001395 if (ret < 0)
1396 {
1397 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001398 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001399 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001400 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001401 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1402 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1403 ret = -EINVAL;
1404 goto exit;
1405 }
1406
1407 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1408 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1409 {
1410 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1411 "lfr mode value %d is out of range"
1412 " (Min: %d Max: %d)", maxTime,
1413 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1414 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1415 ret = -EINVAL;
1416 goto exit;
1417 }
1418
1419 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1420 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1421
1422 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001423
1424 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1425 * where RFS is the RF Switching time. It is twice RFS to consider the
1426 * time to go off channel and return to the home channel. */
1427 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1428 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1429 {
1430 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1431 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1432 " Hence enforcing home away time to disable (0)",
1433 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1434 homeAwayTime = 0;
1435 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1436 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
1437 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001438 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1439 }
1440 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1441 {
1442 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1443 char extra[32];
1444 tANI_U8 len = 0;
1445
1446 /* value is interms of msec */
1447 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1448 if (copy_to_user(priv_data.buf, &extra, len + 1))
1449 {
1450 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1451 "%s: failed to copy data to user buffer", __func__);
1452 ret = -EFAULT;
1453 goto exit;
1454 }
1455 }
1456 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1457 {
1458 tANI_U8 *value = command;
1459 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1460
1461 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1462 value = value + 16;
1463 /* Convert the value from ascii to integer */
1464 ret = kstrtou16(value, 10, &val);
1465 if (ret < 0)
1466 {
1467 /* If the input value is greater than max value of datatype, then also
1468 kstrtou16 fails */
1469 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1470 "%s: kstrtou16 failed range [%d - %d]", __func__,
1471 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1472 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1473 ret = -EINVAL;
1474 goto exit;
1475 }
1476
1477 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1478 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1479 {
1480 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1481 "scan home time value %d is out of range"
1482 " (Min: %d Max: %d)", val,
1483 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1484 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1485 ret = -EINVAL;
1486 goto exit;
1487 }
1488
1489 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1490 "%s: Received Command to change scan home time = %d", __func__, val);
1491
1492 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1493 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1494 }
1495 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1496 {
1497 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1498 char extra[32];
1499 tANI_U8 len = 0;
1500
1501 /* value is interms of msec */
1502 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1503 if (copy_to_user(priv_data.buf, &extra, len + 1))
1504 {
1505 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1506 "%s: failed to copy data to user buffer", __func__);
1507 ret = -EFAULT;
1508 goto exit;
1509 }
1510 }
1511 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1512 {
1513 tANI_U8 *value = command;
1514 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1515
1516 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1517 value = value + 17;
1518 /* Convert the value from ascii to integer */
1519 ret = kstrtou8(value, 10, &val);
1520 if (ret < 0)
1521 {
1522 /* If the input value is greater than max value of datatype, then also
1523 kstrtou8 fails */
1524 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1525 "%s: kstrtou8 failed range [%d - %d]", __func__,
1526 CFG_ROAM_INTRA_BAND_MIN,
1527 CFG_ROAM_INTRA_BAND_MAX);
1528 ret = -EINVAL;
1529 goto exit;
1530 }
1531
1532 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1533 (val > CFG_ROAM_INTRA_BAND_MAX))
1534 {
1535 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1536 "intra band mode value %d is out of range"
1537 " (Min: %d Max: %d)", val,
1538 CFG_ROAM_INTRA_BAND_MIN,
1539 CFG_ROAM_INTRA_BAND_MAX);
1540 ret = -EINVAL;
1541 goto exit;
1542 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001543 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1544 "%s: Received Command to change intra band = %d", __func__, val);
1545
1546 pHddCtx->cfg_ini->nRoamIntraBand = val;
1547 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1548 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001549 else if (strncmp(command, "SETWESMODE", 10) == 0)
1550 {
1551 tANI_U8 *value = command;
1552 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
1553
1554 /* Move pointer to ahead of SETWESMODE<delimiter> */
1555 value = value + 11;
1556 /* Convert the value from ascii to integer */
1557 ret = kstrtou8(value, 10, &wesMode);
1558 if (ret < 0)
1559 {
1560 /* If the input value is greater than max value of datatype, then also
1561 kstrtou8 fails */
1562 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1563 "%s: kstrtou8 failed range [%d - %d]", __func__,
1564 CFG_ENABLE_WES_MODE_NAME_MIN,
1565 CFG_ENABLE_WES_MODE_NAME_MAX);
1566 ret = -EINVAL;
1567 goto exit;
1568 }
1569
1570 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
1571 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
1572 {
1573 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1574 "WES Mode value %d is out of range"
1575 " (Min: %d Max: %d)", wesMode,
1576 CFG_ENABLE_WES_MODE_NAME_MIN,
1577 CFG_ENABLE_WES_MODE_NAME_MAX);
1578 ret = -EINVAL;
1579 goto exit;
1580 }
1581 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1582 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
1583
1584 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
1585 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
1586 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001587 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1588 {
1589 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1590 char extra[32];
1591 tANI_U8 len = 0;
1592
1593 /* value is interms of msec */
1594 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1595 if (copy_to_user(priv_data.buf, &extra, len + 1))
1596 {
1597 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1598 "%s: failed to copy data to user buffer", __func__);
1599 ret = -EFAULT;
1600 goto exit;
1601 }
1602 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001603 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
1604 {
1605 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
1606 char extra[32];
1607 tANI_U8 len = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001608
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001609 len = snprintf(extra, sizeof(extra), "%s %d", command, wesMode);
1610 if (copy_to_user(priv_data.buf, &extra, len + 1))
1611 {
1612 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1613 "%s: failed to copy data to user buffer", __func__);
1614 ret = -EFAULT;
1615 goto exit;
1616 }
1617 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001618 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
1619 {
1620 tANI_U8 *value = command;
1621 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
1622
1623 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
1624 value = value + 15;
1625 /* Convert the value from ascii to integer */
1626 ret = kstrtou8(value, 10, &nProbes);
1627 if (ret < 0)
1628 {
1629 /* If the input value is greater than max value of datatype, then also
1630 kstrtou8 fails */
1631 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1632 "%s: kstrtou8 failed range [%d - %d]", __func__,
1633 CFG_ROAM_SCAN_N_PROBES_MIN,
1634 CFG_ROAM_SCAN_N_PROBES_MAX);
1635 ret = -EINVAL;
1636 goto exit;
1637 }
1638
1639 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
1640 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
1641 {
1642 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1643 "NProbes value %d is out of range"
1644 " (Min: %d Max: %d)", nProbes,
1645 CFG_ROAM_SCAN_N_PROBES_MIN,
1646 CFG_ROAM_SCAN_N_PROBES_MAX);
1647 ret = -EINVAL;
1648 goto exit;
1649 }
1650
1651 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1652 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
1653
1654 pHddCtx->cfg_ini->nProbes = nProbes;
1655 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
1656 }
1657 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
1658 {
1659 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
1660 char extra[32];
1661 tANI_U8 len = 0;
1662
1663 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1664 if (copy_to_user(priv_data.buf, &extra, len + 1))
1665 {
1666 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1667 "%s: failed to copy data to user buffer", __func__);
1668 ret = -EFAULT;
1669 goto exit;
1670 }
1671 }
1672 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
1673 {
1674 tANI_U8 *value = command;
1675 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001676 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001677
1678 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
1679 /* input value is in units of msec */
1680 value = value + 20;
1681 /* Convert the value from ascii to integer */
1682 ret = kstrtou16(value, 10, &homeAwayTime);
1683 if (ret < 0)
1684 {
1685 /* If the input value is greater than max value of datatype, then also
1686 kstrtou8 fails */
1687 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1688 "%s: kstrtou8 failed range [%d - %d]", __func__,
1689 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1690 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1691 ret = -EINVAL;
1692 goto exit;
1693 }
1694
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001695 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
1696 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
1697 {
1698 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1699 "homeAwayTime value %d is out of range"
1700 " (Min: %d Max: %d)", homeAwayTime,
1701 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1702 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1703 ret = -EINVAL;
1704 goto exit;
1705 }
1706
1707 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1708 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
1709
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001710 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1711 * where RFS is the RF Switching time. It is twice RFS to consider the
1712 * time to go off channel and return to the home channel. */
1713 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1714 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1715 {
1716 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1717 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1718 " Hence enforcing home away time to disable (0)",
1719 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1720 homeAwayTime = 0;
1721 }
1722
1723 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
1724 {
1725 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1726 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
1727 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001728 }
1729 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
1730 {
1731 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1732 char extra[32];
1733 tANI_U8 len = 0;
1734
1735 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1736 if (copy_to_user(priv_data.buf, &extra, len + 1))
1737 {
1738 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1739 "%s: failed to copy data to user buffer", __func__);
1740 ret = -EFAULT;
1741 goto exit;
1742 }
1743 }
1744 else if (strncmp(command, "REASSOC", 7) == 0)
1745 {
1746 tANI_U8 *value = command;
1747 tANI_U8 channel = 0;
1748 tSirMacAddr targetApBssid;
1749 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001750#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1751 tCsrHandoffRequest handoffInfo;
1752#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001753 hdd_station_ctx_t *pHddStaCtx = NULL;
1754 tANI_BOOLEAN wesMode = eANI_BOOLEAN_FALSE;
1755 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1756
1757 wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
1758
1759 /* Reassoc command is allowed only if WES mode is enabled */
1760 if (!wesMode)
1761 {
1762 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:WES Mode is not enabled(%d)",__func__, wesMode);
1763 ret = -EINVAL;
1764 goto exit;
1765 }
1766
1767 /* if not associated, no need to proceed with reassoc */
1768 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1769 {
1770 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1771 ret = -EINVAL;
1772 goto exit;
1773 }
1774
1775 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
1776 if (eHAL_STATUS_SUCCESS != status)
1777 {
1778 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1779 "%s: Failed to parse reassoc command data", __func__);
1780 ret = -EINVAL;
1781 goto exit;
1782 }
1783
1784 /* if the target bssid is same as currently associated AP,
1785 then no need to proceed with reassoc */
1786 if (VOS_TRUE == vos_mem_compare(targetApBssid,
1787 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1788 {
1789 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
1790 ret = -EINVAL;
1791 goto exit;
1792 }
1793
1794 /* Check channel number is a valid channel number */
1795 if(VOS_STATUS_SUCCESS !=
1796 wlan_hdd_validate_operation_channel(pAdapter, channel))
1797 {
1798 hddLog(VOS_TRACE_LEVEL_ERROR,
1799 "%s: Invalid Channel [%d] \n", __func__, channel);
1800 return -EINVAL;
1801 }
1802
1803 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001804#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1805 handoffInfo.channel = channel;
1806 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
1807 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
1808#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001809 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001810#endif
1811#ifdef FEATURE_WLAN_LFR
1812 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1813 {
1814 tANI_U8 *value = command;
1815 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1816
1817 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1818 value = value + 12;
1819 /* Convert the value from ascii to integer */
1820 ret = kstrtou8(value, 10, &lfrMode);
1821 if (ret < 0)
1822 {
1823 /* If the input value is greater than max value of datatype, then also
1824 kstrtou8 fails */
1825 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1826 "%s: kstrtou8 failed range [%d - %d]", __func__,
1827 CFG_LFR_FEATURE_ENABLED_MIN,
1828 CFG_LFR_FEATURE_ENABLED_MAX);
1829 ret = -EINVAL;
1830 goto exit;
1831 }
1832
1833 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1834 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1835 {
1836 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1837 "lfr mode value %d is out of range"
1838 " (Min: %d Max: %d)", lfrMode,
1839 CFG_LFR_FEATURE_ENABLED_MIN,
1840 CFG_LFR_FEATURE_ENABLED_MAX);
1841 ret = -EINVAL;
1842 goto exit;
1843 }
1844
1845 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1846 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1847
1848 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1849 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1850 }
1851#endif
1852#ifdef WLAN_FEATURE_VOWIFI_11R
1853 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1854 {
1855 tANI_U8 *value = command;
1856 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1857
1858 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1859 value = value + 18;
1860 /* Convert the value from ascii to integer */
1861 ret = kstrtou8(value, 10, &ft);
1862 if (ret < 0)
1863 {
1864 /* If the input value is greater than max value of datatype, then also
1865 kstrtou8 fails */
1866 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1867 "%s: kstrtou8 failed range [%d - %d]", __func__,
1868 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1869 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1870 ret = -EINVAL;
1871 goto exit;
1872 }
1873
1874 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1875 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1876 {
1877 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1878 "ft mode value %d is out of range"
1879 " (Min: %d Max: %d)", ft,
1880 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1881 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1882 ret = -EINVAL;
1883 goto exit;
1884 }
1885
1886 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1887 "%s: Received Command to change ft mode = %d", __func__, ft);
1888
1889 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1890 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1891 }
1892#endif
1893#ifdef FEATURE_WLAN_CCX
1894 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1895 {
1896 tANI_U8 *value = command;
1897 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1898
1899 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1900 value = value + 11;
1901 /* Convert the value from ascii to integer */
1902 ret = kstrtou8(value, 10, &ccxMode);
1903 if (ret < 0)
1904 {
1905 /* If the input value is greater than max value of datatype, then also
1906 kstrtou8 fails */
1907 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1908 "%s: kstrtou8 failed range [%d - %d]", __func__,
1909 CFG_CCX_FEATURE_ENABLED_MIN,
1910 CFG_CCX_FEATURE_ENABLED_MAX);
1911 ret = -EINVAL;
1912 goto exit;
1913 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001914 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1915 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1916 {
1917 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1918 "Ccx mode value %d is out of range"
1919 " (Min: %d Max: %d)", ccxMode,
1920 CFG_CCX_FEATURE_ENABLED_MIN,
1921 CFG_CCX_FEATURE_ENABLED_MAX);
1922 ret = -EINVAL;
1923 goto exit;
1924 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001925 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1926 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1927
1928 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1929 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1930 }
1931#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001932 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1933 {
1934 tANI_U8 *value = command;
1935 tANI_BOOLEAN roamScanControl = 0;
1936
1937 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1938 value = value + 19;
1939 /* Convert the value from ascii to integer */
1940 ret = kstrtou8(value, 10, &roamScanControl);
1941 if (ret < 0)
1942 {
1943 /* If the input value is greater than max value of datatype, then also
1944 kstrtou8 fails */
1945 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1946 "%s: kstrtou8 failed ", __func__);
1947 ret = -EINVAL;
1948 goto exit;
1949 }
1950
1951 if (0 != roamScanControl)
1952 {
1953 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1954 "roam scan control invalid value = %d",
1955 roamScanControl);
1956 ret = -EINVAL;
1957 goto exit;
1958 }
1959 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1960 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1961
1962 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1963 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001964#ifdef FEATURE_WLAN_OKC
1965 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1966 {
1967 tANI_U8 *value = command;
1968 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1969
1970 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1971 value = value + 11;
1972 /* Convert the value from ascii to integer */
1973 ret = kstrtou8(value, 10, &okcMode);
1974 if (ret < 0)
1975 {
1976 /* If the input value is greater than max value of datatype, then also
1977 kstrtou8 fails */
1978 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1979 "%s: kstrtou8 failed range [%d - %d]", __func__,
1980 CFG_OKC_FEATURE_ENABLED_MIN,
1981 CFG_OKC_FEATURE_ENABLED_MAX);
1982 ret = -EINVAL;
1983 goto exit;
1984 }
1985
1986 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1987 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1988 {
1989 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1990 "Okc mode value %d is out of range"
1991 " (Min: %d Max: %d)", okcMode,
1992 CFG_OKC_FEATURE_ENABLED_MIN,
1993 CFG_OKC_FEATURE_ENABLED_MAX);
1994 ret = -EINVAL;
1995 goto exit;
1996 }
1997
1998 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1999 "%s: Received Command to change okc mode = %d", __func__, okcMode);
2000
2001 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
2002 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002003 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
2004 {
2005 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
2006 char extra[32];
2007 tANI_U8 len = 0;
2008
2009 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
2010 if (copy_to_user(priv_data.buf, &extra, len + 1))
2011 {
2012 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2013 "%s: failed to copy data to user buffer", __func__);
2014 ret = -EFAULT;
2015 goto exit;
2016 }
2017 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002018#endif
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05302019#ifdef WLAN_FEATURE_PACKET_FILTERING
2020 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
2021 {
2022 tANI_U8 filterType = 0;
2023 tANI_U8 *value = command;
2024
2025 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
2026 value = value + 22;
2027
2028 /* Convert the value from ascii to integer */
2029 ret = kstrtou8(value, 10, &filterType);
2030 if (ret < 0)
2031 {
2032 /* If the input value is greater than max value of datatype,
2033 * then also kstrtou8 fails
2034 */
2035 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2036 "%s: kstrtou8 failed range ", __func__);
2037 ret = -EINVAL;
2038 goto exit;
2039 }
2040
2041 if (filterType != 0 && filterType != 1)
2042 {
2043 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2044 "%s: Accepted Values are 0 and 1 ", __func__);
2045 ret = -EINVAL;
2046 goto exit;
2047 }
2048 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
2049 pAdapter->sessionId);
2050 }
2051#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002052 else {
2053 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
2054 __func__, command);
2055 }
2056
Jeff Johnson295189b2012-06-20 16:38:30 -07002057 }
2058exit:
2059 if (command)
2060 {
2061 kfree(command);
2062 }
2063 return ret;
2064}
2065
Srinivas Girigowdade697412013-02-14 16:31:48 -08002066#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2067void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
2068{
2069 eCsrBand band = -1;
2070 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
2071 switch (band)
2072 {
2073 case eCSR_BAND_ALL:
2074 *pBand = WLAN_HDD_UI_BAND_AUTO;
2075 break;
2076
2077 case eCSR_BAND_24:
2078 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
2079 break;
2080
2081 case eCSR_BAND_5G:
2082 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
2083 break;
2084
2085 default:
2086 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2087 *pBand = -1;
2088 break;
2089 }
2090}
2091
2092/**---------------------------------------------------------------------------
2093
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002094 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2095
2096 This function parses the send action frame data passed in the format
2097 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2098
2099 \param - pValue Pointer to input country code revision
2100 \param - pTargetApBssid Pointer to target Ap bssid
2101 \param - pChannel Pointer to the Target AP channel
2102 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2103 \param - pBuf Pointer to data
2104 \param - pBufLen Pointer to data length
2105
2106 \return - 0 for success non-zero for failure
2107
2108 --------------------------------------------------------------------------*/
2109VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2110 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2111{
2112 tANI_U8 *inPtr = pValue;
2113 tANI_U8 *dataEnd;
2114 int tempInt;
2115 int j = 0;
2116 int i = 0;
2117 int v = 0;
2118 tANI_U8 tempBuf[32];
2119 tANI_U8 tempByte = 0;
2120
2121 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2122 /*no argument after the command*/
2123 if (NULL == inPtr)
2124 {
2125 return -EINVAL;
2126 }
2127
2128 /*no space after the command*/
2129 else if (SPACE_ASCII_VALUE != *inPtr)
2130 {
2131 return -EINVAL;
2132 }
2133
2134 /*removing empty spaces*/
2135 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2136
2137 /*no argument followed by spaces*/
2138 if ('\0' == *inPtr)
2139 {
2140 return -EINVAL;
2141 }
2142
2143 /*getting the first argument ie the target AP bssid */
2144 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2145 {
2146 return -EINVAL;
2147 }
2148 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2149 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2150 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2151
2152 /* point to the next argument */
2153 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2154 /*no argument after the command*/
2155 if (NULL == inPtr) return -EINVAL;
2156
2157 /*removing empty spaces*/
2158 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2159
2160 /*no argument followed by spaces*/
2161 if ('\0' == *inPtr)
2162 {
2163 return -EINVAL;
2164 }
2165
2166 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002167 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002168 v = kstrtos32(tempBuf, 10, &tempInt);
2169 if ( v < 0) return -EINVAL;
2170
2171 *pChannel = tempInt;
2172
2173 /* point to the next argument */
2174 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2175 /*no argument after the command*/
2176 if (NULL == inPtr) return -EINVAL;
2177 /*removing empty spaces*/
2178 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2179
2180 /*no argument followed by spaces*/
2181 if ('\0' == *inPtr)
2182 {
2183 return -EINVAL;
2184 }
2185
2186 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07002187 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002188 v = kstrtos32(tempBuf, 10, &tempInt);
2189 if ( v < 0) return -EINVAL;
2190
2191 *pDwellTime = tempInt;
2192
2193 /* point to the next argument */
2194 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2195 /*no argument after the command*/
2196 if (NULL == inPtr) return -EINVAL;
2197 /*removing empty spaces*/
2198 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2199
2200 /*no argument followed by spaces*/
2201 if ('\0' == *inPtr)
2202 {
2203 return -EINVAL;
2204 }
2205
2206 /* find the length of data */
2207 dataEnd = inPtr;
2208 while(('\0' != *dataEnd) )
2209 {
2210 dataEnd++;
2211 ++(*pBufLen);
2212 }
2213 if ( *pBufLen <= 0) return -EINVAL;
2214
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07002215 /* Allocate the number of bytes based on the number of input characters
2216 whether it is even or odd.
2217 if the number of input characters are even, then we need N/2 byte.
2218 if the number of input characters are odd, then we need do (N+1)/2 to
2219 compensate rounding off.
2220 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
2221 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
2222 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002223 if (NULL == *pBuf)
2224 {
2225 hddLog(VOS_TRACE_LEVEL_FATAL,
2226 "%s: vos_mem_alloc failed ", __func__);
2227 return -EINVAL;
2228 }
2229
2230 /* the buffer received from the upper layer is character buffer,
2231 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2232 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2233 and f0 in 3rd location */
2234 for (i = 0, j = 0; j < *pBufLen; j += 2)
2235 {
2236 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2237 (*pBuf)[i++] = tempByte;
2238 }
2239 *pBufLen = i;
2240 return VOS_STATUS_SUCCESS;
2241}
2242
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002243/**---------------------------------------------------------------------------
2244
Srinivas Girigowdade697412013-02-14 16:31:48 -08002245 \brief hdd_parse_countryrev() - HDD Parse country code revision
2246
2247 This function parses the country code revision passed in the format
2248 SETCOUNTRYREV<space><Country code><space>revision
2249
2250 \param - pValue Pointer to input country code revision
2251 \param - pCountryCode Pointer to local output array to record country code
2252 \param - pRevision Pointer to store revision integer number
2253
2254 \return - 0 for success non-zero for failure
2255
2256 --------------------------------------------------------------------------*/
2257VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
2258{
2259 tANI_U8 *inPtr = pValue;
2260 int tempInt;
2261
2262 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2263 /*no argument after the command*/
2264 if (NULL == inPtr)
2265 {
2266 return -EINVAL;
2267 }
2268
2269 /*no space after the command*/
2270 else if (SPACE_ASCII_VALUE != *inPtr)
2271 {
2272 return -EINVAL;
2273 }
2274
2275 /*removing empty spaces*/
2276 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
2277
2278 /*no argument followed by spaces*/
2279 if ('\0' == *inPtr)
2280 {
2281 return -EINVAL;
2282 }
2283
2284 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07002285 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002286
2287 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2288 "Country code is : %s", pCountryCode);
2289
2290 /*inPtr pointing to the beginning of first space after country code */
2291 inPtr = strpbrk( inPtr, " " );
2292 /*no revision number after the country code argument */
2293 if (NULL == inPtr)
2294 {
2295 return -EINVAL;
2296 }
2297
2298 inPtr++;
2299
2300 /*removing empty space*/
2301 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2302
2303 /*no channel list after the number of channels argument and spaces*/
2304 if (0 == strncmp(pCountryCode, "KR", 2))
2305 {
2306 if ('\0' == *inPtr)
2307 {
2308 return -EINVAL;
2309 }
2310
2311 sscanf(inPtr, "%d", &tempInt);
2312 *pRevision = tempInt;
2313 }
2314 else
2315 {
2316 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2317 "Revision input is required only for Country KR");
2318 return -EINVAL;
2319 }
2320 return VOS_STATUS_SUCCESS;
2321}
2322
2323/**---------------------------------------------------------------------------
2324
2325 \brief hdd_parse_channellist() - HDD Parse channel list
2326
2327 This function parses the channel list passed in the format
2328 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002329 if the Number of channels (N) does not match with the actual number of channels passed
2330 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2331 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2332 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2333 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002334
2335 \param - pValue Pointer to input channel list
2336 \param - ChannelList Pointer to local output array to record channel list
2337 \param - pNumChannels Pointer to number of roam scan channels
2338
2339 \return - 0 for success non-zero for failure
2340
2341 --------------------------------------------------------------------------*/
2342VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2343{
2344 tANI_U8 *inPtr = pValue;
2345 int tempInt;
2346 int j = 0;
2347 int v = 0;
2348 char buf[32];
2349
2350 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2351 /*no argument after the command*/
2352 if (NULL == inPtr)
2353 {
2354 return -EINVAL;
2355 }
2356
2357 /*no space after the command*/
2358 else if (SPACE_ASCII_VALUE != *inPtr)
2359 {
2360 return -EINVAL;
2361 }
2362
2363 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002364 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002365
2366 /*no argument followed by spaces*/
2367 if ('\0' == *inPtr)
2368 {
2369 return -EINVAL;
2370 }
2371
2372 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002373 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002374 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002375 if ((v < 0) ||
2376 (tempInt <= 0) ||
2377 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2378 {
2379 return -EINVAL;
2380 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002381
2382 *pNumChannels = tempInt;
2383
2384 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2385 "Number of channels are: %d", *pNumChannels);
2386
2387 for (j = 0; j < (*pNumChannels); j++)
2388 {
2389 /*inPtr pointing to the beginning of first space after number of channels*/
2390 inPtr = strpbrk( inPtr, " " );
2391 /*no channel list after the number of channels argument*/
2392 if (NULL == 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
2405 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002406 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002407
2408 /*no channel list after the number of channels argument and spaces*/
2409 if ( '\0' == *inPtr )
2410 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002411 if (0 != j)
2412 {
2413 *pNumChannels = j;
2414 return VOS_STATUS_SUCCESS;
2415 }
2416 else
2417 {
2418 return -EINVAL;
2419 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002420 }
2421
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002422 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002423 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002424 if ((v < 0) ||
2425 (tempInt <= 0) ||
2426 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2427 {
2428 return -EINVAL;
2429 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002430 pChannelList[j] = tempInt;
2431
2432 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2433 "Channel %d added to preferred channel list",
2434 pChannelList[j] );
2435 }
2436
Srinivas Girigowdade697412013-02-14 16:31:48 -08002437 return VOS_STATUS_SUCCESS;
2438}
2439
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002440
2441/**---------------------------------------------------------------------------
2442
2443 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2444
2445 This function parses the reasoc command data passed in the format
2446 REASSOC<space><bssid><space><channel>
2447
2448 \param - pValue Pointer to input country code revision
2449 \param - pTargetApBssid Pointer to target Ap bssid
2450 \param - pChannel Pointer to the Target AP channel
2451
2452 \return - 0 for success non-zero for failure
2453
2454 --------------------------------------------------------------------------*/
2455VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2456{
2457 tANI_U8 *inPtr = pValue;
2458 int tempInt;
2459 int v = 0;
2460 tANI_U8 tempBuf[32];
2461
2462 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2463 /*no argument after the command*/
2464 if (NULL == inPtr)
2465 {
2466 return -EINVAL;
2467 }
2468
2469 /*no space after the command*/
2470 else if (SPACE_ASCII_VALUE != *inPtr)
2471 {
2472 return -EINVAL;
2473 }
2474
2475 /*removing empty spaces*/
2476 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2477
2478 /*no argument followed by spaces*/
2479 if ('\0' == *inPtr)
2480 {
2481 return -EINVAL;
2482 }
2483
2484 /*getting the first argument ie the target AP bssid */
2485 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2486 {
2487 return -EINVAL;
2488 }
2489 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2490 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2491 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2492
2493 /* point to the next argument */
2494 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2495 /*no argument after the command*/
2496 if (NULL == inPtr) return -EINVAL;
2497
2498 /*removing empty spaces*/
2499 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2500
2501 /*no argument followed by spaces*/
2502 if ('\0' == *inPtr)
2503 {
2504 return -EINVAL;
2505 }
2506
2507 /*getting the next argument ie the channel number */
2508 sscanf(inPtr, "%s ", tempBuf);
2509 v = kstrtos32(tempBuf, 10, &tempInt);
2510 if ( v < 0) return -EINVAL;
2511
2512 *pChannel = tempInt;
2513 return VOS_STATUS_SUCCESS;
2514}
2515
2516#endif
2517
Jeff Johnson295189b2012-06-20 16:38:30 -07002518/**---------------------------------------------------------------------------
2519
2520 \brief hdd_open() - HDD Open function
2521
2522 This is called in response to ifconfig up
2523
2524 \param - dev Pointer to net_device structure
2525
2526 \return - 0 for success non-zero for failure
2527
2528 --------------------------------------------------------------------------*/
2529int hdd_open (struct net_device *dev)
2530{
2531 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2532 hdd_context_t *pHddCtx;
2533 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2534 VOS_STATUS status;
2535 v_BOOL_t in_standby = TRUE;
2536
2537 if (NULL == pAdapter)
2538 {
2539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002540 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002541 return -ENODEV;
2542 }
2543
2544 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2545 if (NULL == pHddCtx)
2546 {
2547 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002548 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002549 return -ENODEV;
2550 }
2551
2552 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2553 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2554 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002555 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2556 {
2557 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302558 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002559 in_standby = FALSE;
2560 break;
2561 }
2562 else
2563 {
2564 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2565 pAdapterNode = pNext;
2566 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002567 }
2568
2569 if (TRUE == in_standby)
2570 {
2571 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2572 {
2573 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2574 "wlan out of power save", __func__);
2575 return -EINVAL;
2576 }
2577 }
2578
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002579 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002580 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2581 {
2582 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002583 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002584 /* Enable TX queues only when we are connected */
2585 netif_tx_start_all_queues(dev);
2586 }
2587
2588 return 0;
2589}
2590
2591int hdd_mon_open (struct net_device *dev)
2592{
2593 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2594
2595 if(pAdapter == NULL) {
2596 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002597 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002598 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002599 }
2600
2601 netif_start_queue(dev);
2602
2603 return 0;
2604}
2605/**---------------------------------------------------------------------------
2606
2607 \brief hdd_stop() - HDD stop function
2608
2609 This is called in response to ifconfig down
2610
2611 \param - dev Pointer to net_device structure
2612
2613 \return - 0 for success non-zero for failure
2614
2615 --------------------------------------------------------------------------*/
2616
2617int hdd_stop (struct net_device *dev)
2618{
2619 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2620 hdd_context_t *pHddCtx;
2621 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2622 VOS_STATUS status;
2623 v_BOOL_t enter_standby = TRUE;
2624
2625 ENTER();
2626
2627 if (NULL == pAdapter)
2628 {
2629 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002630 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002631 return -ENODEV;
2632 }
2633
2634 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2635 if (NULL == pHddCtx)
2636 {
2637 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002638 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002639 return -ENODEV;
2640 }
2641
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002642 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002643 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2644 netif_tx_disable(pAdapter->dev);
2645 netif_carrier_off(pAdapter->dev);
2646
2647
2648 /* SoftAP ifaces should never go in power save mode
2649 making sure same here. */
2650 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2651 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002652 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002653 )
2654 {
2655 /* SoftAP mode, so return from here */
2656 EXIT();
2657 return 0;
2658 }
2659
2660 /* Find if any iface is up then
2661 if any iface is up then can't put device to sleep/ power save mode. */
2662 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2663 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2664 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002665 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2666 {
2667 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302668 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002669 enter_standby = FALSE;
2670 break;
2671 }
2672 else
2673 {
2674 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2675 pAdapterNode = pNext;
2676 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002677 }
2678
2679 if (TRUE == enter_standby)
2680 {
2681 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2682 "entering standby", __func__);
2683 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2684 {
2685 /*log and return success*/
2686 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2687 "wlan in power save", __func__);
2688 }
2689 }
2690
2691 EXIT();
2692 return 0;
2693}
2694
2695/**---------------------------------------------------------------------------
2696
2697 \brief hdd_uninit() - HDD uninit function
2698
2699 This is called during the netdev unregister to uninitialize all data
2700associated with the device
2701
2702 \param - dev Pointer to net_device structure
2703
2704 \return - void
2705
2706 --------------------------------------------------------------------------*/
2707static void hdd_uninit (struct net_device *dev)
2708{
2709 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2710
2711 ENTER();
2712
2713 do
2714 {
2715 if (NULL == pAdapter)
2716 {
2717 hddLog(VOS_TRACE_LEVEL_FATAL,
2718 "%s: NULL pAdapter", __func__);
2719 break;
2720 }
2721
2722 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2723 {
2724 hddLog(VOS_TRACE_LEVEL_FATAL,
2725 "%s: Invalid magic", __func__);
2726 break;
2727 }
2728
2729 if (NULL == pAdapter->pHddCtx)
2730 {
2731 hddLog(VOS_TRACE_LEVEL_FATAL,
2732 "%s: NULL pHddCtx", __func__);
2733 break;
2734 }
2735
2736 if (dev != pAdapter->dev)
2737 {
2738 hddLog(VOS_TRACE_LEVEL_FATAL,
2739 "%s: Invalid device reference", __func__);
2740 /* we haven't validated all cases so let this go for now */
2741 }
2742
2743 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2744
2745 /* after uninit our adapter structure will no longer be valid */
2746 pAdapter->dev = NULL;
2747 pAdapter->magic = 0;
2748 } while (0);
2749
2750 EXIT();
2751}
2752
2753/**---------------------------------------------------------------------------
2754
2755 \brief hdd_release_firmware() -
2756
2757 This function calls the release firmware API to free the firmware buffer.
2758
2759 \param - pFileName Pointer to the File Name.
2760 pCtx - Pointer to the adapter .
2761
2762
2763 \return - 0 for success, non zero for failure
2764
2765 --------------------------------------------------------------------------*/
2766
2767VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2768{
2769 VOS_STATUS status = VOS_STATUS_SUCCESS;
2770 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2771 ENTER();
2772
2773
2774 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2775
2776 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2777
2778 if(pHddCtx->fw) {
2779 release_firmware(pHddCtx->fw);
2780 pHddCtx->fw = NULL;
2781 }
2782 else
2783 status = VOS_STATUS_E_FAILURE;
2784 }
2785 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2786 if(pHddCtx->nv) {
2787 release_firmware(pHddCtx->nv);
2788 pHddCtx->nv = NULL;
2789 }
2790 else
2791 status = VOS_STATUS_E_FAILURE;
2792
2793 }
2794
2795 EXIT();
2796 return status;
2797}
2798
2799/**---------------------------------------------------------------------------
2800
2801 \brief hdd_request_firmware() -
2802
2803 This function reads the firmware file using the request firmware
2804 API and returns the the firmware data and the firmware file size.
2805
2806 \param - pfileName - Pointer to the file name.
2807 - pCtx - Pointer to the adapter .
2808 - ppfw_data - Pointer to the pointer of the firmware data.
2809 - pSize - Pointer to the file size.
2810
2811 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2812
2813 --------------------------------------------------------------------------*/
2814
2815
2816VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2817{
2818 int status;
2819 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2820 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2821 ENTER();
2822
2823 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2824
2825 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2826
2827 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2828 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2829 __func__, pfileName);
2830 retval = VOS_STATUS_E_FAILURE;
2831 }
2832
2833 else {
2834 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2835 *pSize = pHddCtx->fw->size;
2836 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2837 __func__, *pSize);
2838 }
2839 }
2840 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2841
2842 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2843
2844 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2845 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2846 __func__, pfileName);
2847 retval = VOS_STATUS_E_FAILURE;
2848 }
2849
2850 else {
2851 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2852 *pSize = pHddCtx->nv->size;
2853 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2854 __func__, *pSize);
2855 }
2856 }
2857
2858 EXIT();
2859 return retval;
2860}
2861/**---------------------------------------------------------------------------
2862 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2863
2864 This is the function invoked by SME to inform the result of a full power
2865 request issued by HDD
2866
2867 \param - callbackcontext - Pointer to cookie
2868 status - result of request
2869
2870 \return - None
2871
2872--------------------------------------------------------------------------*/
2873void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2874{
2875 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2876
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002877 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002878 if(&pHddCtx->full_pwr_comp_var)
2879 {
2880 complete(&pHddCtx->full_pwr_comp_var);
2881 }
2882}
2883
2884/**---------------------------------------------------------------------------
2885
2886 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2887
2888 This is the function invoked by SME to inform the result of BMPS
2889 request issued by HDD
2890
2891 \param - callbackcontext - Pointer to cookie
2892 status - result of request
2893
2894 \return - None
2895
2896--------------------------------------------------------------------------*/
2897void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2898{
2899
2900 struct completion *completion_var = (struct completion*) callbackContext;
2901
2902 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2903 if(completion_var != NULL)
2904 {
2905 complete(completion_var);
2906 }
2907}
2908
2909/**---------------------------------------------------------------------------
2910
2911 \brief hdd_get_cfg_file_size() -
2912
2913 This function reads the configuration file using the request firmware
2914 API and returns the configuration file size.
2915
2916 \param - pCtx - Pointer to the adapter .
2917 - pFileName - Pointer to the file name.
2918 - pBufSize - Pointer to the buffer size.
2919
2920 \return - 0 for success, non zero for failure
2921
2922 --------------------------------------------------------------------------*/
2923
2924VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2925{
2926 int status;
2927 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2928
2929 ENTER();
2930
2931 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2932
2933 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2934 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2935 status = VOS_STATUS_E_FAILURE;
2936 }
2937 else {
2938 *pBufSize = pHddCtx->fw->size;
2939 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2940 release_firmware(pHddCtx->fw);
2941 pHddCtx->fw = NULL;
2942 }
2943
2944 EXIT();
2945 return VOS_STATUS_SUCCESS;
2946}
2947
2948/**---------------------------------------------------------------------------
2949
2950 \brief hdd_read_cfg_file() -
2951
2952 This function reads the configuration file using the request firmware
2953 API and returns the cfg data and the buffer size of the configuration file.
2954
2955 \param - pCtx - Pointer to the adapter .
2956 - pFileName - Pointer to the file name.
2957 - pBuffer - Pointer to the data buffer.
2958 - pBufSize - Pointer to the buffer size.
2959
2960 \return - 0 for success, non zero for failure
2961
2962 --------------------------------------------------------------------------*/
2963
2964VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2965 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2966{
2967 int status;
2968 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2969
2970 ENTER();
2971
2972 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2973
2974 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2975 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2976 return VOS_STATUS_E_FAILURE;
2977 }
2978 else {
2979 if(*pBufSize != pHddCtx->fw->size) {
2980 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2981 "file size", __func__);
2982 release_firmware(pHddCtx->fw);
2983 pHddCtx->fw = NULL;
2984 return VOS_STATUS_E_FAILURE;
2985 }
2986 else {
2987 if(pBuffer) {
2988 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2989 }
2990 release_firmware(pHddCtx->fw);
2991 pHddCtx->fw = NULL;
2992 }
2993 }
2994
2995 EXIT();
2996
2997 return VOS_STATUS_SUCCESS;
2998}
2999
3000/**---------------------------------------------------------------------------
3001
Jeff Johnson295189b2012-06-20 16:38:30 -07003002 \brief hdd_set_mac_address() -
3003
3004 This function sets the user specified mac address using
3005 the command ifconfig wlanX hw ether <mac adress>.
3006
3007 \param - dev - Pointer to the net device.
3008 - addr - Pointer to the sockaddr.
3009 \return - 0 for success, non zero for failure
3010
3011 --------------------------------------------------------------------------*/
3012
3013static int hdd_set_mac_address(struct net_device *dev, void *addr)
3014{
3015 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3016 struct sockaddr *psta_mac_addr = addr;
3017 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3018
3019 ENTER();
3020
3021 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
3022
3023#ifdef HDD_SESSIONIZE
3024 // set the MAC address though the STA ID CFG.
3025 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
3026 (v_U8_t *)&pAdapter->macAddressCurrent,
3027 sizeof( pAdapter->macAddressCurrent ),
3028 hdd_set_mac_addr_cb, VOS_FALSE );
3029#endif
3030
3031 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
3032
3033 EXIT();
3034 return halStatus;
3035}
3036
3037tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
3038{
3039 int i;
3040 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3041 {
3042 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
3043 break;
3044 }
3045
3046 if( VOS_MAX_CONCURRENCY_PERSONA == i)
3047 return NULL;
3048
3049 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
3050 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
3051}
3052
3053void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
3054{
3055 int i;
3056 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3057 {
3058 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
3059 {
3060 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
3061 break;
3062 }
3063 }
3064 return;
3065}
3066
3067#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3068 static struct net_device_ops wlan_drv_ops = {
3069 .ndo_open = hdd_open,
3070 .ndo_stop = hdd_stop,
3071 .ndo_uninit = hdd_uninit,
3072 .ndo_start_xmit = hdd_hard_start_xmit,
3073 .ndo_tx_timeout = hdd_tx_timeout,
3074 .ndo_get_stats = hdd_stats,
3075 .ndo_do_ioctl = hdd_ioctl,
3076 .ndo_set_mac_address = hdd_set_mac_address,
3077 .ndo_select_queue = hdd_select_queue,
3078#ifdef WLAN_FEATURE_PACKET_FILTERING
3079#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
3080 .ndo_set_rx_mode = hdd_set_multicast_list,
3081#else
3082 .ndo_set_multicast_list = hdd_set_multicast_list,
3083#endif //LINUX_VERSION_CODE
3084#endif
3085 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003086 static struct net_device_ops wlan_mon_drv_ops = {
3087 .ndo_open = hdd_mon_open,
3088 .ndo_stop = hdd_stop,
3089 .ndo_uninit = hdd_uninit,
3090 .ndo_start_xmit = hdd_mon_hard_start_xmit,
3091 .ndo_tx_timeout = hdd_tx_timeout,
3092 .ndo_get_stats = hdd_stats,
3093 .ndo_do_ioctl = hdd_ioctl,
3094 .ndo_set_mac_address = hdd_set_mac_address,
3095 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003096
3097#endif
3098
3099void hdd_set_station_ops( struct net_device *pWlanDev )
3100{
3101#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3102 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3103 pWlanDev->netdev_ops = &wlan_drv_ops;
3104#else
3105 pWlanDev->open = hdd_open;
3106 pWlanDev->stop = hdd_stop;
3107 pWlanDev->uninit = hdd_uninit;
3108 pWlanDev->hard_start_xmit = NULL;
3109 pWlanDev->tx_timeout = hdd_tx_timeout;
3110 pWlanDev->get_stats = hdd_stats;
3111 pWlanDev->do_ioctl = hdd_ioctl;
3112 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3113 pWlanDev->set_mac_address = hdd_set_mac_address;
3114#endif
3115}
3116
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003117static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003118{
3119 struct net_device *pWlanDev = NULL;
3120 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003121 /*
3122 * cfg80211 initialization and registration....
3123 */
3124 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3125
Jeff Johnson295189b2012-06-20 16:38:30 -07003126 if(pWlanDev != NULL)
3127 {
3128
3129 //Save the pointer to the net_device in the HDD adapter
3130 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3131
Jeff Johnson295189b2012-06-20 16:38:30 -07003132 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3133
3134 pAdapter->dev = pWlanDev;
3135 pAdapter->pHddCtx = pHddCtx;
3136 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3137
3138 init_completion(&pAdapter->session_open_comp_var);
3139 init_completion(&pAdapter->session_close_comp_var);
3140 init_completion(&pAdapter->disconnect_comp_var);
3141 init_completion(&pAdapter->linkup_event_var);
3142 init_completion(&pAdapter->cancel_rem_on_chan_var);
3143 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003144#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3145 init_completion(&pAdapter->offchannel_tx_event);
3146#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003147 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003148#ifdef FEATURE_WLAN_TDLS
3149 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003150 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003151 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303152 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003153#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003154 init_completion(&pHddCtx->mc_sus_event_var);
3155 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05303156 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003157 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07003158
Jeff Johnson295189b2012-06-20 16:38:30 -07003159 pAdapter->isLinkUpSvcNeeded = FALSE;
3160 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3161 //Init the net_device structure
3162 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3163
3164 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3165 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3166 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3167 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3168
3169 hdd_set_station_ops( pAdapter->dev );
3170
3171 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003172 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3173 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3174 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003175 /* set pWlanDev's parent to underlying device */
3176 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3177 }
3178
3179 return pAdapter;
3180}
3181
3182VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3183{
3184 struct net_device *pWlanDev = pAdapter->dev;
3185 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3186 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3187 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3188
3189 if( rtnl_lock_held )
3190 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003191 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003192 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3193 {
3194 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3195 return VOS_STATUS_E_FAILURE;
3196 }
3197 }
3198 if (register_netdevice(pWlanDev))
3199 {
3200 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3201 return VOS_STATUS_E_FAILURE;
3202 }
3203 }
3204 else
3205 {
3206 if(register_netdev(pWlanDev))
3207 {
3208 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3209 return VOS_STATUS_E_FAILURE;
3210 }
3211 }
3212 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3213
3214 return VOS_STATUS_SUCCESS;
3215}
3216
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003217static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003218{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003219 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003220
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003221 if (NULL == pAdapter)
3222 {
3223 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3224 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003225 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003226
3227 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3228 {
3229 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3230 return eHAL_STATUS_NOT_INITIALIZED;
3231 }
3232
3233 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3234
3235 /* need to make sure all of our scheduled work has completed.
3236 * This callback is called from MC thread context, so it is safe to
3237 * to call below flush workqueue API from here.
3238 */
3239 flush_scheduled_work();
3240
3241 /* We can be blocked while waiting for scheduled work to be
3242 * flushed, and the adapter structure can potentially be freed, in
3243 * which case the magic will have been reset. So make sure the
3244 * magic is still good, and hence the adapter structure is still
3245 * valid, before signaling completion */
3246 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3247 {
3248 complete(&pAdapter->session_close_comp_var);
3249 }
3250
Jeff Johnson295189b2012-06-20 16:38:30 -07003251 return eHAL_STATUS_SUCCESS;
3252}
3253
3254VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3255{
3256 struct net_device *pWlanDev = pAdapter->dev;
3257 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3258 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3259 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3260 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3261 int rc = 0;
3262
3263 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003264 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003265 //Open a SME session for future operation
3266 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003267 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07003268 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3269 {
3270 hddLog(VOS_TRACE_LEVEL_FATAL,
3271 "sme_OpenSession() failed with status code %08d [x%08lx]",
3272 halStatus, halStatus );
3273 status = VOS_STATUS_E_FAILURE;
3274 goto error_sme_open;
3275 }
3276
3277 //Block on a completion variable. Can't wait forever though.
3278 rc = wait_for_completion_interruptible_timeout(
3279 &pAdapter->session_open_comp_var,
3280 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3281 if (!rc)
3282 {
3283 hddLog(VOS_TRACE_LEVEL_FATAL,
3284 "Session is not opened within timeout period code %08d", rc );
3285 status = VOS_STATUS_E_FAILURE;
3286 goto error_sme_open;
3287 }
3288
3289 // Register wireless extensions
3290 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3291 {
3292 hddLog(VOS_TRACE_LEVEL_FATAL,
3293 "hdd_register_wext() failed with status code %08d [x%08lx]",
3294 halStatus, halStatus );
3295 status = VOS_STATUS_E_FAILURE;
3296 goto error_register_wext;
3297 }
3298 //Safe to register the hard_start_xmit function again
3299#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3300 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3301#else
3302 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3303#endif
3304
3305 //Set the Connection State to Not Connected
3306 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3307
3308 //Set the default operation channel
3309 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3310
3311 /* Make the default Auth Type as OPEN*/
3312 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3313
3314 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3315 {
3316 hddLog(VOS_TRACE_LEVEL_FATAL,
3317 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3318 status, status );
3319 goto error_init_txrx;
3320 }
3321
3322 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3323
3324 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3325 {
3326 hddLog(VOS_TRACE_LEVEL_FATAL,
3327 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3328 status, status );
3329 goto error_wmm_init;
3330 }
3331
3332 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3333
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003334#ifdef FEATURE_WLAN_TDLS
3335 if(0 != wlan_hdd_tdls_init(pAdapter))
3336 {
3337 status = VOS_STATUS_E_FAILURE;
3338 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3339 goto error_tdls_init;
3340 }
3341 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3342#endif
3343
Jeff Johnson295189b2012-06-20 16:38:30 -07003344 return VOS_STATUS_SUCCESS;
3345
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003346#ifdef FEATURE_WLAN_TDLS
3347error_tdls_init:
3348 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3349 hdd_wmm_adapter_close(pAdapter);
3350#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003351error_wmm_init:
3352 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3353 hdd_deinit_tx_rx(pAdapter);
3354error_init_txrx:
3355 hdd_UnregisterWext(pWlanDev);
3356error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003357 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003358 {
3359 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003360 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003361 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003362 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003363 {
3364 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003365 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003366 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003367 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003368 }
3369}
3370error_sme_open:
3371 return status;
3372}
3373
Jeff Johnson295189b2012-06-20 16:38:30 -07003374void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3375{
3376 hdd_cfg80211_state_t *cfgState;
3377
3378 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3379
3380 if( NULL != cfgState->buf )
3381 {
3382 int rc;
3383 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3384 rc = wait_for_completion_interruptible_timeout(
3385 &pAdapter->tx_action_cnf_event,
3386 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3387 if(!rc)
3388 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003389 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003390 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3391 }
3392 }
3393 return;
3394}
Jeff Johnson295189b2012-06-20 16:38:30 -07003395
3396void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3397{
3398 ENTER();
3399 switch ( pAdapter->device_mode )
3400 {
3401 case WLAN_HDD_INFRA_STATION:
3402 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003403 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003404 {
3405 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3406 {
3407 hdd_deinit_tx_rx( pAdapter );
3408 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3409 }
3410
3411 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3412 {
3413 hdd_wmm_adapter_close( pAdapter );
3414 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3415 }
3416
Jeff Johnson295189b2012-06-20 16:38:30 -07003417 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003418#ifdef FEATURE_WLAN_TDLS
3419 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3420 {
3421 wlan_hdd_tdls_exit(pAdapter);
3422 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3423 }
3424#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003425
3426 break;
3427 }
3428
3429 case WLAN_HDD_SOFTAP:
3430 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003431 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003432 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003433
3434 hdd_unregister_hostapd(pAdapter);
3435 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003436 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003437 break;
3438 }
3439
3440 case WLAN_HDD_MONITOR:
3441 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003442 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003443 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3444 {
3445 hdd_deinit_tx_rx( pAdapter );
3446 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3447 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003448 if(NULL != pAdapterforTx)
3449 {
3450 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3451 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003452 break;
3453 }
3454
3455
3456 default:
3457 break;
3458 }
3459
3460 EXIT();
3461}
3462
3463void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3464{
3465 struct net_device *pWlanDev = pAdapter->dev;
3466
3467 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3468 if( rtnl_held )
3469 {
3470 unregister_netdevice(pWlanDev);
3471 }
3472 else
3473 {
3474 unregister_netdev(pWlanDev);
3475 }
3476 // note that the pAdapter is no longer valid at this point
3477 // since the memory has been reclaimed
3478 }
3479
3480}
3481
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003482void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3483{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303484 VOS_STATUS status;
3485 hdd_adapter_t *pAdapter = NULL;
3486 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003487
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303488 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003489
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303490 /*loop through all adapters.*/
3491 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003492 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303493 pAdapter = pAdapterNode->pAdapter;
3494 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
3495 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003496
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303497 { // we skip this registration for modes other than STA and P2P client modes.
3498 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3499 pAdapterNode = pNext;
3500 continue;
3501 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003502
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303503 //Apply Dynamic DTIM For P2P
3504 //Only if ignoreDynamicDtimInP2pMode is not set in ini
3505 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
3506 pHddCtx->cfg_ini->enableModulatedDTIM) &&
3507 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3508 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
3509 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
3510 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
3511 (eConnectionState_Associated ==
3512 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
3513 (pHddCtx->cfg_ini->fIsBmpsEnabled))
3514 {
3515 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003516
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303517 powerRequest.uIgnoreDTIM = 1;
3518 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
3519
3520 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3521 {
3522 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3523 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3524 }
3525 else
3526 {
3527 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3528 }
3529
3530 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3531 * specified during Enter/Exit BMPS when LCD off*/
3532 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3533 NULL, eANI_BOOLEAN_FALSE);
3534 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3535 NULL, eANI_BOOLEAN_FALSE);
3536
3537 /* switch to the DTIM specified in cfg.ini */
3538 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3539 "Switch to DTIM %d", powerRequest.uListenInterval);
3540 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3541 break;
3542
3543 }
3544
3545 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3546 pAdapterNode = pNext;
3547 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003548}
3549
3550void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3551{
3552 /*Switch back to DTIM 1*/
3553 tSirSetPowerParamsReq powerRequest = { 0 };
3554
3555 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3556 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003557 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003558
3559 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3560 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3561 NULL, eANI_BOOLEAN_FALSE);
3562 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3563 NULL, eANI_BOOLEAN_FALSE);
3564
3565 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3566 "Switch to DTIM%d",powerRequest.uListenInterval);
3567 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3568
3569}
3570
Jeff Johnson295189b2012-06-20 16:38:30 -07003571VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3572{
3573 VOS_STATUS status = VOS_STATUS_SUCCESS;
3574
3575 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3576 {
3577 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3578 }
3579
3580 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3581 {
3582 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3583 }
3584
3585 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3586 {
3587 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3588 }
3589
3590 return status;
3591}
3592
3593VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3594{
3595 hdd_adapter_t *pAdapter = NULL;
3596 eHalStatus halStatus;
3597 VOS_STATUS status = VOS_STATUS_E_INVAL;
3598 v_BOOL_t disableBmps = FALSE;
3599 v_BOOL_t disableImps = FALSE;
3600
3601 switch(session_type)
3602 {
3603 case WLAN_HDD_INFRA_STATION:
3604 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003605 case WLAN_HDD_P2P_CLIENT:
3606 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003607 //Exit BMPS -> Is Sta/P2P Client is already connected
3608 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3609 if((NULL != pAdapter)&&
3610 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3611 {
3612 disableBmps = TRUE;
3613 }
3614
3615 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3616 if((NULL != pAdapter)&&
3617 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3618 {
3619 disableBmps = TRUE;
3620 }
3621
3622 //Exit both Bmps and Imps incase of Go/SAP Mode
3623 if((WLAN_HDD_SOFTAP == session_type) ||
3624 (WLAN_HDD_P2P_GO == session_type))
3625 {
3626 disableBmps = TRUE;
3627 disableImps = TRUE;
3628 }
3629
3630 if(TRUE == disableImps)
3631 {
3632 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3633 {
3634 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3635 }
3636 }
3637
3638 if(TRUE == disableBmps)
3639 {
3640 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3641 {
3642 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3643
3644 if(eHAL_STATUS_SUCCESS != halStatus)
3645 {
3646 status = VOS_STATUS_E_FAILURE;
3647 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3648 VOS_ASSERT(0);
3649 return status;
3650 }
3651 }
3652
3653 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3654 {
3655 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3656
3657 if(eHAL_STATUS_SUCCESS != halStatus)
3658 {
3659 status = VOS_STATUS_E_FAILURE;
3660 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3661 VOS_ASSERT(0);
3662 return status;
3663 }
3664 }
3665 }
3666
3667 if((TRUE == disableBmps) ||
3668 (TRUE == disableImps))
3669 {
3670 /* Now, get the chip into Full Power now */
3671 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3672 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3673 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3674
3675 if(halStatus != eHAL_STATUS_SUCCESS)
3676 {
3677 if(halStatus == eHAL_STATUS_PMC_PENDING)
3678 {
3679 //Block on a completion variable. Can't wait forever though
3680 wait_for_completion_interruptible_timeout(
3681 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3682 }
3683 else
3684 {
3685 status = VOS_STATUS_E_FAILURE;
3686 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3687 VOS_ASSERT(0);
3688 return status;
3689 }
3690 }
3691
3692 status = VOS_STATUS_SUCCESS;
3693 }
3694
3695 break;
3696 }
3697 return status;
3698}
3699
3700hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003701 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003702 tANI_U8 rtnl_held )
3703{
3704 hdd_adapter_t *pAdapter = NULL;
3705 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3706 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3707 VOS_STATUS exitbmpsStatus;
3708
3709 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3710
3711 //Disable BMPS incase of Concurrency
3712 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3713
3714 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3715 {
3716 //Fail to Exit BMPS
3717 VOS_ASSERT(0);
3718 return NULL;
3719 }
3720
3721 switch(session_type)
3722 {
3723 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003724 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003725 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003726 {
3727 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3728
3729 if( NULL == pAdapter )
3730 return NULL;
3731
Jeff Johnsone7245742012-09-05 17:12:55 -07003732 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3733 NL80211_IFTYPE_P2P_CLIENT:
3734 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003735
Jeff Johnson295189b2012-06-20 16:38:30 -07003736 pAdapter->device_mode = session_type;
3737
3738 status = hdd_init_station_mode( pAdapter );
3739 if( VOS_STATUS_SUCCESS != status )
3740 goto err_free_netdev;
3741
3742 status = hdd_register_interface( pAdapter, rtnl_held );
3743 if( VOS_STATUS_SUCCESS != status )
3744 {
3745 hdd_deinit_adapter(pHddCtx, pAdapter);
3746 goto err_free_netdev;
3747 }
3748 //Stop the Interface TX queue.
3749 netif_tx_disable(pAdapter->dev);
3750 //netif_tx_disable(pWlanDev);
3751 netif_carrier_off(pAdapter->dev);
3752
3753 break;
3754 }
3755
Jeff Johnson295189b2012-06-20 16:38:30 -07003756 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003757 case WLAN_HDD_SOFTAP:
3758 {
3759 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3760 if( NULL == pAdapter )
3761 return NULL;
3762
Jeff Johnson295189b2012-06-20 16:38:30 -07003763 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3764 NL80211_IFTYPE_AP:
3765 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003766 pAdapter->device_mode = session_type;
3767
3768 status = hdd_init_ap_mode(pAdapter);
3769 if( VOS_STATUS_SUCCESS != status )
3770 goto err_free_netdev;
3771
3772 status = hdd_register_hostapd( pAdapter, rtnl_held );
3773 if( VOS_STATUS_SUCCESS != status )
3774 {
3775 hdd_deinit_adapter(pHddCtx, pAdapter);
3776 goto err_free_netdev;
3777 }
3778
3779 netif_tx_disable(pAdapter->dev);
3780 netif_carrier_off(pAdapter->dev);
3781
3782 hdd_set_conparam( 1 );
3783 break;
3784 }
3785 case WLAN_HDD_MONITOR:
3786 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003787 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3788 if( NULL == pAdapter )
3789 return NULL;
3790
3791 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3792 pAdapter->device_mode = session_type;
3793 status = hdd_register_interface( pAdapter, rtnl_held );
3794#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3795 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3796#else
3797 pAdapter->dev->open = hdd_mon_open;
3798 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3799#endif
3800 hdd_init_tx_rx( pAdapter );
3801 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3802 //Set adapter to be used for data tx. It will use either GO or softap.
3803 pAdapter->sessionCtx.monitor.pAdapterForTx =
3804 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003805 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3806 {
3807 pAdapter->sessionCtx.monitor.pAdapterForTx =
3808 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3809 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003810 /* This workqueue will be used to transmit management packet over
3811 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003812 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3813 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3814 return NULL;
3815 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003816
Jeff Johnson295189b2012-06-20 16:38:30 -07003817 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3818 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003819 }
3820 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003821 case WLAN_HDD_FTM:
3822 {
3823 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3824
3825 if( NULL == pAdapter )
3826 return NULL;
3827 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3828 * message while loading driver in FTM mode. */
3829 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3830 pAdapter->device_mode = session_type;
3831 status = hdd_register_interface( pAdapter, rtnl_held );
3832 }
3833 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003834 default:
3835 {
3836 VOS_ASSERT(0);
3837 return NULL;
3838 }
3839 }
3840
3841
3842 if( VOS_STATUS_SUCCESS == status )
3843 {
3844 //Add it to the hdd's session list.
3845 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3846 if( NULL == pHddAdapterNode )
3847 {
3848 status = VOS_STATUS_E_NOMEM;
3849 }
3850 else
3851 {
3852 pHddAdapterNode->pAdapter = pAdapter;
3853 status = hdd_add_adapter_back ( pHddCtx,
3854 pHddAdapterNode );
3855 }
3856 }
3857
3858 if( VOS_STATUS_SUCCESS != status )
3859 {
3860 if( NULL != pAdapter )
3861 {
3862 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3863 pAdapter = NULL;
3864 }
3865 if( NULL != pHddAdapterNode )
3866 {
3867 vos_mem_free( pHddAdapterNode );
3868 }
3869
3870 goto resume_bmps;
3871 }
3872
3873 if(VOS_STATUS_SUCCESS == status)
3874 {
3875 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3876
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003877 //Initialize the WoWL service
3878 if(!hdd_init_wowl(pAdapter))
3879 {
3880 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3881 goto err_free_netdev;
3882 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003883 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003884 return pAdapter;
3885
3886err_free_netdev:
3887 free_netdev(pAdapter->dev);
3888 wlan_hdd_release_intf_addr( pHddCtx,
3889 pAdapter->macAddressCurrent.bytes );
3890
3891resume_bmps:
3892 //If bmps disabled enable it
3893 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3894 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303895 if (pHddCtx->hdd_wlan_suspended)
3896 {
3897 hdd_set_pwrparams(pHddCtx);
3898 }
3899 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003900 }
3901 return NULL;
3902}
3903
3904VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3905 tANI_U8 rtnl_held )
3906{
3907 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3908 VOS_STATUS status;
3909
3910 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3911 if( VOS_STATUS_SUCCESS != status )
3912 return status;
3913
3914 while ( pCurrent->pAdapter != pAdapter )
3915 {
3916 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3917 if( VOS_STATUS_SUCCESS != status )
3918 break;
3919
3920 pCurrent = pNext;
3921 }
3922 pAdapterNode = pCurrent;
3923 if( VOS_STATUS_SUCCESS == status )
3924 {
3925 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3926 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3927 hdd_remove_adapter( pHddCtx, pAdapterNode );
3928 vos_mem_free( pAdapterNode );
3929
Jeff Johnson295189b2012-06-20 16:38:30 -07003930
3931 /* If there is a single session of STA/P2P client, re-enable BMPS */
3932 if ((!vos_concurrent_sessions_running()) &&
3933 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3934 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3935 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303936 if (pHddCtx->hdd_wlan_suspended)
3937 {
3938 hdd_set_pwrparams(pHddCtx);
3939 }
3940 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003941 }
3942
3943 return VOS_STATUS_SUCCESS;
3944 }
3945
3946 return VOS_STATUS_E_FAILURE;
3947}
3948
3949VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3950{
3951 hdd_adapter_list_node_t *pHddAdapterNode;
3952 VOS_STATUS status;
3953
3954 ENTER();
3955
3956 do
3957 {
3958 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3959 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3960 {
3961 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3962 vos_mem_free( pHddAdapterNode );
3963 }
3964 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3965
3966 EXIT();
3967
3968 return VOS_STATUS_SUCCESS;
3969}
3970
3971void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3972{
3973 v_U8_t addIE[1] = {0};
3974
3975 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3976 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3977 eANI_BOOLEAN_FALSE) )
3978 {
3979 hddLog(LOGE,
3980 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3981 }
3982
3983 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3984 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3985 eANI_BOOLEAN_FALSE) )
3986 {
3987 hddLog(LOGE,
3988 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3989 }
3990
3991 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3992 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3993 eANI_BOOLEAN_FALSE) )
3994 {
3995 hddLog(LOGE,
3996 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3997 }
3998}
3999
4000VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4001{
4002 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4003 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4004 union iwreq_data wrqu;
4005
4006 ENTER();
4007
4008 switch(pAdapter->device_mode)
4009 {
4010 case WLAN_HDD_INFRA_STATION:
4011 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004012 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07004013 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4014 {
4015 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
4016 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4017 pAdapter->sessionId,
4018 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
4019 else
4020 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
4021 pAdapter->sessionId,
4022 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4023 //success implies disconnect command got queued up successfully
4024 if(halStatus == eHAL_STATUS_SUCCESS)
4025 {
4026 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
4027 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4028 }
4029 memset(&wrqu, '\0', sizeof(wrqu));
4030 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4031 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4032 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
4033 }
4034 else
4035 {
4036 hdd_abort_mac_scan(pHddCtx);
4037 }
4038
4039 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
4040 {
4041 INIT_COMPLETION(pAdapter->session_close_comp_var);
4042 if (eHAL_STATUS_SUCCESS ==
4043 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
4044 hdd_smeCloseSessionCallback, pAdapter))
4045 {
4046 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004047 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07004048 &pAdapter->session_close_comp_var,
4049 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
4050 }
4051 }
4052
4053 break;
4054
4055 case WLAN_HDD_SOFTAP:
4056 case WLAN_HDD_P2P_GO:
4057 //Any softap specific cleanup here...
4058 mutex_lock(&pHddCtx->sap_lock);
4059 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4060 {
4061 VOS_STATUS status;
4062 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4063
4064 //Stop Bss.
4065 status = WLANSAP_StopBss(pHddCtx->pvosContext);
4066 if (VOS_IS_STATUS_SUCCESS(status))
4067 {
4068 hdd_hostapd_state_t *pHostapdState =
4069 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4070
4071 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
4072
4073 if (!VOS_IS_STATUS_SUCCESS(status))
4074 {
4075 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004076 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004077 }
4078 }
4079 else
4080 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004081 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004082 }
4083 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
4084
4085 if (eHAL_STATUS_FAILURE ==
4086 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4087 0, NULL, eANI_BOOLEAN_FALSE))
4088 {
4089 hddLog(LOGE,
4090 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004091 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004092 }
4093
4094 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
4095 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
4096 eANI_BOOLEAN_FALSE) )
4097 {
4098 hddLog(LOGE,
4099 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
4100 }
4101
4102 // Reset WNI_CFG_PROBE_RSP Flags
4103 wlan_hdd_reset_prob_rspies(pAdapter);
4104 kfree(pAdapter->sessionCtx.ap.beacon);
4105 pAdapter->sessionCtx.ap.beacon = NULL;
4106 }
4107 mutex_unlock(&pHddCtx->sap_lock);
4108 break;
4109 case WLAN_HDD_MONITOR:
4110 break;
4111 default:
4112 break;
4113 }
4114
4115 EXIT();
4116 return VOS_STATUS_SUCCESS;
4117}
4118
4119VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
4120{
4121 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4122 VOS_STATUS status;
4123 hdd_adapter_t *pAdapter;
4124
4125 ENTER();
4126
4127 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4128
4129 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4130 {
4131 pAdapter = pAdapterNode->pAdapter;
4132 netif_tx_disable(pAdapter->dev);
4133 netif_carrier_off(pAdapter->dev);
4134
4135 hdd_stop_adapter( pHddCtx, pAdapter );
4136
4137 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4138 pAdapterNode = pNext;
4139 }
4140
4141 EXIT();
4142
4143 return VOS_STATUS_SUCCESS;
4144}
4145
4146VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4147{
4148 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4149 VOS_STATUS status;
4150 hdd_adapter_t *pAdapter;
4151
4152 ENTER();
4153
4154 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4155
4156 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4157 {
4158 pAdapter = pAdapterNode->pAdapter;
4159 netif_tx_disable(pAdapter->dev);
4160 netif_carrier_off(pAdapter->dev);
4161
Jeff Johnson295189b2012-06-20 16:38:30 -07004162 hdd_deinit_tx_rx(pAdapter);
4163 hdd_wmm_adapter_close(pAdapter);
4164
4165 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4166 pAdapterNode = pNext;
4167 }
4168
4169 EXIT();
4170
4171 return VOS_STATUS_SUCCESS;
4172}
4173
4174VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4175{
4176 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4177 VOS_STATUS status;
4178 hdd_adapter_t *pAdapter;
4179 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304180 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07004181
4182 ENTER();
4183
4184 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4185
4186 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4187 {
4188 pAdapter = pAdapterNode->pAdapter;
4189
4190 switch(pAdapter->device_mode)
4191 {
4192 case WLAN_HDD_INFRA_STATION:
4193 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004194 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304195
4196 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
4197
Jeff Johnson295189b2012-06-20 16:38:30 -07004198 hdd_init_station_mode(pAdapter);
4199 /* Open the gates for HDD to receive Wext commands */
4200 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004201 pHddCtx->scan_info.mScanPending = FALSE;
4202 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004203
4204 //Trigger the initial scan
4205 hdd_wlan_initial_scan(pAdapter);
4206
4207 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304208 if (eConnectionState_Associated == connState ||
4209 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07004210 {
4211 union iwreq_data wrqu;
4212 memset(&wrqu, '\0', sizeof(wrqu));
4213 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4214 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4215 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004216
Jeff Johnson295189b2012-06-20 16:38:30 -07004217 /* indicate disconnected event to nl80211 */
4218 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4219 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004220 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304221 else if (eConnectionState_Connecting == connState)
4222 {
4223 /*
4224 * Indicate connect failure to supplicant if we were in the
4225 * process of connecting
4226 */
4227 cfg80211_connect_result(pAdapter->dev, NULL,
4228 NULL, 0, NULL, 0,
4229 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4230 GFP_KERNEL);
4231 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004232 break;
4233
4234 case WLAN_HDD_SOFTAP:
4235 /* softAP can handle SSR */
4236 break;
4237
4238 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004239 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
4240 __func__);
4241 /* event supplicant to restart */
4242 cfg80211_del_sta(pAdapter->dev,
4243 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004244 break;
4245
4246 case WLAN_HDD_MONITOR:
4247 /* monitor interface start */
4248 break;
4249 default:
4250 break;
4251 }
4252
4253 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4254 pAdapterNode = pNext;
4255 }
4256
4257 EXIT();
4258
4259 return VOS_STATUS_SUCCESS;
4260}
4261
4262VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4263{
4264 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4265 hdd_adapter_t *pAdapter;
4266 VOS_STATUS status;
4267 v_U32_t roamId;
4268
4269 ENTER();
4270
4271 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4272
4273 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4274 {
4275 pAdapter = pAdapterNode->pAdapter;
4276
4277 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4278 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4279 {
4280 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4281 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4282
4283 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4284 init_completion(&pAdapter->disconnect_comp_var);
4285 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4286 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4287
4288 wait_for_completion_interruptible_timeout(
4289 &pAdapter->disconnect_comp_var,
4290 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4291
4292 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4293 pHddCtx->isAmpAllowed = VOS_FALSE;
4294 sme_RoamConnect(pHddCtx->hHal,
4295 pAdapter->sessionId, &(pWextState->roamProfile),
4296 &roamId);
4297 }
4298
4299 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4300 pAdapterNode = pNext;
4301 }
4302
4303 EXIT();
4304
4305 return VOS_STATUS_SUCCESS;
4306}
4307
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004308void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4309{
4310 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4311 VOS_STATUS status;
4312 hdd_adapter_t *pAdapter;
4313 hdd_station_ctx_t *pHddStaCtx;
4314 hdd_ap_ctx_t *pHddApCtx;
4315 hdd_hostapd_state_t * pHostapdState;
4316 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4317 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4318 const char *p2pMode = "DEV";
4319 const char *ccMode = "Standalone";
4320 int n;
4321
4322 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4323 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4324 {
4325 pAdapter = pAdapterNode->pAdapter;
4326 switch (pAdapter->device_mode) {
4327 case WLAN_HDD_INFRA_STATION:
4328 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4329 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4330 staChannel = pHddStaCtx->conn_info.operationChannel;
4331 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4332 }
4333 break;
4334 case WLAN_HDD_P2P_CLIENT:
4335 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4336 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4337 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4338 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4339 p2pMode = "CLI";
4340 }
4341 break;
4342 case WLAN_HDD_P2P_GO:
4343 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4344 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4345 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4346 p2pChannel = pHddApCtx->operatingChannel;
4347 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4348 }
4349 p2pMode = "GO";
4350 break;
4351 case WLAN_HDD_SOFTAP:
4352 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4353 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4354 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4355 apChannel = pHddApCtx->operatingChannel;
4356 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4357 }
4358 break;
4359 default:
4360 break;
4361 }
4362 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4363 pAdapterNode = pNext;
4364 }
4365 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4366 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4367 }
4368 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4369 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4370 if (p2pChannel > 0) {
4371 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4372 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4373 }
4374 if (apChannel > 0) {
4375 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4376 apChannel, MAC_ADDR_ARRAY(apBssid));
4377 }
4378
4379 if (p2pChannel > 0 && apChannel > 0) {
4380 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4381 }
4382}
4383
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004384bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004385{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004386 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004387}
4388
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004389/* Once SSR is disabled then it cannot be set. */
4390void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004391{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004392 if (HDD_SSR_DISABLED == isSsrRequired)
4393 return;
4394
Jeff Johnson295189b2012-06-20 16:38:30 -07004395 isSsrRequired = value;
4396}
4397
4398VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4399 hdd_adapter_list_node_t** ppAdapterNode)
4400{
4401 VOS_STATUS status;
4402 spin_lock(&pHddCtx->hddAdapters.lock);
4403 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4404 (hdd_list_node_t**) ppAdapterNode );
4405 spin_unlock(&pHddCtx->hddAdapters.lock);
4406 return status;
4407}
4408
4409VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4410 hdd_adapter_list_node_t* pAdapterNode,
4411 hdd_adapter_list_node_t** pNextAdapterNode)
4412{
4413 VOS_STATUS status;
4414 spin_lock(&pHddCtx->hddAdapters.lock);
4415 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4416 (hdd_list_node_t*) pAdapterNode,
4417 (hdd_list_node_t**)pNextAdapterNode );
4418
4419 spin_unlock(&pHddCtx->hddAdapters.lock);
4420 return status;
4421}
4422
4423VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4424 hdd_adapter_list_node_t* pAdapterNode)
4425{
4426 VOS_STATUS status;
4427 spin_lock(&pHddCtx->hddAdapters.lock);
4428 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4429 &pAdapterNode->node );
4430 spin_unlock(&pHddCtx->hddAdapters.lock);
4431 return status;
4432}
4433
4434VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4435 hdd_adapter_list_node_t** ppAdapterNode)
4436{
4437 VOS_STATUS status;
4438 spin_lock(&pHddCtx->hddAdapters.lock);
4439 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4440 (hdd_list_node_t**) ppAdapterNode );
4441 spin_unlock(&pHddCtx->hddAdapters.lock);
4442 return status;
4443}
4444
4445VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4446 hdd_adapter_list_node_t* pAdapterNode)
4447{
4448 VOS_STATUS status;
4449 spin_lock(&pHddCtx->hddAdapters.lock);
4450 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4451 (hdd_list_node_t*) pAdapterNode );
4452 spin_unlock(&pHddCtx->hddAdapters.lock);
4453 return status;
4454}
4455
4456VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4457 hdd_adapter_list_node_t* pAdapterNode)
4458{
4459 VOS_STATUS status;
4460 spin_lock(&pHddCtx->hddAdapters.lock);
4461 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4462 (hdd_list_node_t*) pAdapterNode );
4463 spin_unlock(&pHddCtx->hddAdapters.lock);
4464 return status;
4465}
4466
4467hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4468 tSirMacAddr macAddr )
4469{
4470 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4471 hdd_adapter_t *pAdapter;
4472 VOS_STATUS status;
4473
4474 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4475
4476 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4477 {
4478 pAdapter = pAdapterNode->pAdapter;
4479
4480 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4481 macAddr, sizeof(tSirMacAddr) ) )
4482 {
4483 return pAdapter;
4484 }
4485 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4486 pAdapterNode = pNext;
4487 }
4488
4489 return NULL;
4490
4491}
4492
4493hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4494{
4495 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4496 hdd_adapter_t *pAdapter;
4497 VOS_STATUS status;
4498
4499 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4500
4501 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4502 {
4503 pAdapter = pAdapterNode->pAdapter;
4504
4505 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4506 IFNAMSIZ ) )
4507 {
4508 return pAdapter;
4509 }
4510 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4511 pAdapterNode = pNext;
4512 }
4513
4514 return NULL;
4515
4516}
4517
4518hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4519{
4520 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4521 hdd_adapter_t *pAdapter;
4522 VOS_STATUS status;
4523
4524 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4525
4526 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4527 {
4528 pAdapter = pAdapterNode->pAdapter;
4529
4530 if( pAdapter && (mode == pAdapter->device_mode) )
4531 {
4532 return pAdapter;
4533 }
4534 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4535 pAdapterNode = pNext;
4536 }
4537
4538 return NULL;
4539
4540}
4541
4542//Remove this function later
4543hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4544{
4545 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4546 hdd_adapter_t *pAdapter;
4547 VOS_STATUS status;
4548
4549 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4550
4551 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4552 {
4553 pAdapter = pAdapterNode->pAdapter;
4554
4555 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4556 {
4557 return pAdapter;
4558 }
4559
4560 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4561 pAdapterNode = pNext;
4562 }
4563
4564 return NULL;
4565
4566}
4567
Jeff Johnson295189b2012-06-20 16:38:30 -07004568/**---------------------------------------------------------------------------
4569
4570 \brief hdd_set_monitor_tx_adapter() -
4571
4572 This API initializes the adapter to be used while transmitting on monitor
4573 adapter.
4574
4575 \param - pHddCtx - Pointer to the HDD context.
4576 pAdapter - Adapter that will used for TX. This can be NULL.
4577 \return - None.
4578 --------------------------------------------------------------------------*/
4579void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4580{
4581 hdd_adapter_t *pMonAdapter;
4582
4583 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4584
4585 if( NULL != pMonAdapter )
4586 {
4587 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4588 }
4589}
Jeff Johnson295189b2012-06-20 16:38:30 -07004590/**---------------------------------------------------------------------------
4591
4592 \brief hdd_select_queue() -
4593
4594 This API returns the operating channel of the requested device mode
4595
4596 \param - pHddCtx - Pointer to the HDD context.
4597 - mode - Device mode for which operating channel is required
4598 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4599 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4600 \return - channel number. "0" id the requested device is not found OR it is not connected.
4601 --------------------------------------------------------------------------*/
4602v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4603{
4604 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4605 VOS_STATUS status;
4606 hdd_adapter_t *pAdapter;
4607 v_U8_t operatingChannel = 0;
4608
4609 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4610
4611 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4612 {
4613 pAdapter = pAdapterNode->pAdapter;
4614
4615 if( mode == pAdapter->device_mode )
4616 {
4617 switch(pAdapter->device_mode)
4618 {
4619 case WLAN_HDD_INFRA_STATION:
4620 case WLAN_HDD_P2P_CLIENT:
4621 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4622 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4623 break;
4624 case WLAN_HDD_SOFTAP:
4625 case WLAN_HDD_P2P_GO:
4626 /*softap connection info */
4627 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4628 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4629 break;
4630 default:
4631 break;
4632 }
4633
4634 break; //Found the device of interest. break the loop
4635 }
4636
4637 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4638 pAdapterNode = pNext;
4639 }
4640 return operatingChannel;
4641}
4642
4643#ifdef WLAN_FEATURE_PACKET_FILTERING
4644/**---------------------------------------------------------------------------
4645
4646 \brief hdd_set_multicast_list() -
4647
4648 This used to set the multicast address list.
4649
4650 \param - dev - Pointer to the WLAN device.
4651 - skb - Pointer to OS packet (sk_buff).
4652 \return - success/fail
4653
4654 --------------------------------------------------------------------------*/
4655static void hdd_set_multicast_list(struct net_device *dev)
4656{
4657 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004658 int mc_count;
4659 int i = 0;
4660 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304661
4662 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004663 {
4664 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304665 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004666 return;
4667 }
4668
4669 if (dev->flags & IFF_ALLMULTI)
4670 {
4671 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004672 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304673 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004674 }
4675 else
4676 {
4677 mc_count = netdev_mc_count(dev);
4678 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004679 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004680 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4681 {
4682 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004683 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304684 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004685 return;
4686 }
4687
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304688 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004689
4690 netdev_for_each_mc_addr(ha, dev) {
4691 if (i == mc_count)
4692 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304693 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4694 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4695 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004696 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304697 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004698 i++;
4699 }
4700 }
4701 return;
4702}
4703#endif
4704
4705/**---------------------------------------------------------------------------
4706
4707 \brief hdd_select_queue() -
4708
4709 This function is registered with the Linux OS for network
4710 core to decide which queue to use first.
4711
4712 \param - dev - Pointer to the WLAN device.
4713 - skb - Pointer to OS packet (sk_buff).
4714 \return - ac, Queue Index/access category corresponding to UP in IP header
4715
4716 --------------------------------------------------------------------------*/
4717v_U16_t hdd_select_queue(struct net_device *dev,
4718 struct sk_buff *skb)
4719{
4720 return hdd_wmm_select_queue(dev, skb);
4721}
4722
4723
4724/**---------------------------------------------------------------------------
4725
4726 \brief hdd_wlan_initial_scan() -
4727
4728 This function triggers the initial scan
4729
4730 \param - pAdapter - Pointer to the HDD adapter.
4731
4732 --------------------------------------------------------------------------*/
4733void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4734{
4735 tCsrScanRequest scanReq;
4736 tCsrChannelInfo channelInfo;
4737 eHalStatus halStatus;
4738 unsigned long scanId;
4739 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4740
4741 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4742 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4743 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4744
4745 if(sme_Is11dSupported(pHddCtx->hHal))
4746 {
4747 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4748 if ( HAL_STATUS_SUCCESS( halStatus ) )
4749 {
4750 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4751 if( !scanReq.ChannelInfo.ChannelList )
4752 {
4753 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4754 vos_mem_free(channelInfo.ChannelList);
4755 return;
4756 }
4757 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4758 channelInfo.numOfChannels);
4759 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4760 vos_mem_free(channelInfo.ChannelList);
4761 }
4762
4763 scanReq.scanType = eSIR_PASSIVE_SCAN;
4764 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4765 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4766 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4767 }
4768 else
4769 {
4770 scanReq.scanType = eSIR_ACTIVE_SCAN;
4771 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4772 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4773 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4774 }
4775
4776 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4777 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4778 {
4779 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4780 __func__, halStatus );
4781 }
4782
4783 if(sme_Is11dSupported(pHddCtx->hHal))
4784 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4785}
4786
4787struct fullPowerContext
4788{
4789 struct completion completion;
4790 unsigned int magic;
4791};
4792#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4793
4794/**---------------------------------------------------------------------------
4795
4796 \brief hdd_full_power_callback() - HDD full power callback function
4797
4798 This is the function invoked by SME to inform the result of a full power
4799 request issued by HDD
4800
4801 \param - callbackcontext - Pointer to cookie
4802 \param - status - result of request
4803
4804 \return - None
4805
4806 --------------------------------------------------------------------------*/
4807static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4808{
4809 struct fullPowerContext *pContext = callbackContext;
4810
4811 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304812 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004813
4814 if (NULL == callbackContext)
4815 {
4816 hddLog(VOS_TRACE_LEVEL_ERROR,
4817 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004818 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004819 return;
4820 }
4821
4822 /* there is a race condition that exists between this callback function
4823 and the caller since the caller could time out either before or
4824 while this code is executing. we'll assume the timeout hasn't
4825 occurred, but we'll verify that right before we save our work */
4826
4827 if (POWER_CONTEXT_MAGIC != pContext->magic)
4828 {
4829 /* the caller presumably timed out so there is nothing we can do */
4830 hddLog(VOS_TRACE_LEVEL_WARN,
4831 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004832 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004833 return;
4834 }
4835
4836 /* the race is on. caller could have timed out immediately after
4837 we verified the magic, but if so, caller will wait a short time
4838 for us to notify the caller, so the context will stay valid */
4839 complete(&pContext->completion);
4840}
4841
4842/**---------------------------------------------------------------------------
4843
4844 \brief hdd_wlan_exit() - HDD WLAN exit function
4845
4846 This is the driver exit point (invoked during rmmod)
4847
4848 \param - pHddCtx - Pointer to the HDD Context
4849
4850 \return - None
4851
4852 --------------------------------------------------------------------------*/
4853void hdd_wlan_exit(hdd_context_t *pHddCtx)
4854{
4855 eHalStatus halStatus;
4856 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4857 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304858 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004859 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004860 struct fullPowerContext powerContext;
4861 long lrc;
4862
4863 ENTER();
4864
Jeff Johnson88ba7742013-02-27 14:36:02 -08004865 if (VOS_FTM_MODE != hdd_get_conparam())
4866 {
4867 // Unloading, restart logic is no more required.
4868 wlan_hdd_restart_deinit(pHddCtx);
4869 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004870
Jeff Johnson295189b2012-06-20 16:38:30 -07004871 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004872 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004873 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004874 {
4875 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4876 WLAN_HDD_INFRA_STATION);
4877 if (pAdapter == NULL)
4878 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4879
4880 if (pAdapter != NULL)
4881 {
4882 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4883 hdd_UnregisterWext(pAdapter->dev);
4884 }
4885 }
4886 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004887
Jeff Johnson295189b2012-06-20 16:38:30 -07004888 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004889 {
4890 wlan_hdd_ftm_close(pHddCtx);
4891 goto free_hdd_ctx;
4892 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004893 //Stop the Interface TX queue.
4894 //netif_tx_disable(pWlanDev);
4895 //netif_carrier_off(pWlanDev);
4896
Jeff Johnson295189b2012-06-20 16:38:30 -07004897 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4898 {
4899 pAdapter = hdd_get_adapter(pHddCtx,
4900 WLAN_HDD_SOFTAP);
4901 }
4902 else
4903 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004904 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004905 {
4906 pAdapter = hdd_get_adapter(pHddCtx,
4907 WLAN_HDD_INFRA_STATION);
4908 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004909 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004910 /* DeRegister with platform driver as client for Suspend/Resume */
4911 vosStatus = hddDeregisterPmOps(pHddCtx);
4912 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4913 {
4914 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4915 VOS_ASSERT(0);
4916 }
4917
4918 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4919 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4920 {
4921 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4922 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004923
4924 // Cancel any outstanding scan requests. We are about to close all
4925 // of our adapters, but an adapter structure is what SME passes back
4926 // to our callback function. Hence if there are any outstanding scan
4927 // requests then there is a race condition between when the adapter
4928 // is closed and when the callback is invoked. We try to resolve that
4929 // race condition here by canceling any outstanding scans before we
4930 // close the adapters.
4931 // Note that the scans may be cancelled in an asynchronous manner, so
4932 // ideally there needs to be some kind of synchronization. Rather than
4933 // introduce a new synchronization here, we will utilize the fact that
4934 // we are about to Request Full Power, and since that is synchronized,
4935 // the expectation is that by the time Request Full Power has completed,
4936 // all scans will be cancelled.
4937 hdd_abort_mac_scan( pHddCtx );
4938
4939 //Disable IMPS/BMPS as we do not want the device to enter any power
4940 //save mode during shutdown
4941 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4942 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4943 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4944
4945 //Ensure that device is in full power as we will touch H/W during vos_Stop
4946 init_completion(&powerContext.completion);
4947 powerContext.magic = POWER_CONTEXT_MAGIC;
4948
4949 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4950 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4951
4952 if (eHAL_STATUS_SUCCESS != halStatus)
4953 {
4954 if (eHAL_STATUS_PMC_PENDING == halStatus)
4955 {
4956 /* request was sent -- wait for the response */
4957 lrc = wait_for_completion_interruptible_timeout(
4958 &powerContext.completion,
4959 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4960 /* either we have a response or we timed out
4961 either way, first invalidate our magic */
4962 powerContext.magic = 0;
4963 if (lrc <= 0)
4964 {
4965 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004966 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004967 /* there is a race condition such that the callback
4968 function could be executing at the same time we are. of
4969 primary concern is if the callback function had already
4970 verified the "magic" but hasn't yet set the completion
4971 variable. Since the completion variable is on our
4972 stack, we'll delay just a bit to make sure the data is
4973 still valid if that is the case */
4974 msleep(50);
4975 }
4976 }
4977 else
4978 {
4979 hddLog(VOS_TRACE_LEVEL_ERROR,
4980 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004981 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004982 VOS_ASSERT(0);
4983 /* continue -- need to clean up as much as possible */
4984 }
4985 }
4986
4987 // Unregister the Net Device Notifier
4988 unregister_netdevice_notifier(&hdd_netdev_notifier);
4989
Jeff Johnson295189b2012-06-20 16:38:30 -07004990 hdd_stop_all_adapters( pHddCtx );
4991
Jeff Johnson295189b2012-06-20 16:38:30 -07004992#ifdef WLAN_BTAMP_FEATURE
4993 vosStatus = WLANBAP_Stop(pVosContext);
4994 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4995 {
4996 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4997 "%s: Failed to stop BAP",__func__);
4998 }
4999#endif //WLAN_BTAMP_FEATURE
5000
5001 //Stop all the modules
5002 vosStatus = vos_stop( pVosContext );
5003 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
5004 {
5005 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5006 "%s: Failed to stop VOSS",__func__);
5007 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5008 }
5009
Jeff Johnson295189b2012-06-20 16:38:30 -07005010 //Assert Deep sleep signal now to put Libra HW in lowest power state
5011 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5012 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5013
5014 //Vote off any PMIC voltage supplies
5015 vos_chipPowerDown(NULL, NULL, NULL);
5016
5017 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
5018
Jeff Johnson295189b2012-06-20 16:38:30 -07005019 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07005020 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005021
5022 //Close the scheduler before calling vos_close to make sure no thread is
5023 // scheduled after the each module close is called i.e after all the data
5024 // structures are freed.
5025 vosStatus = vos_sched_close( pVosContext );
5026 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
5027 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5028 "%s: Failed to close VOSS Scheduler",__func__);
5029 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
5030 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005031#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005032#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5033 /* Destroy the wake lock */
5034 wake_lock_destroy(&pHddCtx->rx_wake_lock);
5035#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005036 /* Destroy the wake lock */
5037 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005038#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005039
5040 //Close VOSS
5041 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
5042 vos_close(pVosContext);
5043
Jeff Johnson295189b2012-06-20 16:38:30 -07005044 //Close Watchdog
5045 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5046 vos_watchdog_close(pVosContext);
5047
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05305048 //Clean up HDD Nlink Service
5049 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
5050 nl_srv_exit();
5051
Jeff Johnson295189b2012-06-20 16:38:30 -07005052 /* Cancel the vote for XO Core ON.
5053 * This is done here to ensure there is no race condition since MC, TX and WD threads have
5054 * exited at this point
5055 */
5056 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
5057 " when WLAN is turned OFF\n");
5058 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5059 {
5060 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
5061 " Not returning failure."
5062 " Power consumed will be high\n");
5063 }
5064
5065 hdd_close_all_adapters( pHddCtx );
5066
5067
5068 //Free up dynamically allocated members inside HDD Adapter
5069 kfree(pHddCtx->cfg_ini);
5070 pHddCtx->cfg_ini= NULL;
5071
5072 /* free the power on lock from platform driver */
5073 if (free_riva_power_on_lock("wlan"))
5074 {
5075 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
5076 __func__);
5077 }
5078
Jeff Johnson88ba7742013-02-27 14:36:02 -08005079free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08005080 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005081 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005082 if (hdd_is_ssr_required())
5083 {
5084 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07005085 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07005086 msleep(5000);
5087 }
5088 hdd_set_ssr_required (VOS_FALSE);
5089}
5090
5091
5092/**---------------------------------------------------------------------------
5093
5094 \brief hdd_update_config_from_nv() - Function to update the contents of
5095 the running configuration with parameters taken from NV storage
5096
5097 \param - pHddCtx - Pointer to the HDD global context
5098
5099 \return - VOS_STATUS_SUCCESS if successful
5100
5101 --------------------------------------------------------------------------*/
5102static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
5103{
Jeff Johnson295189b2012-06-20 16:38:30 -07005104 v_BOOL_t itemIsValid = VOS_FALSE;
5105 VOS_STATUS status;
5106 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
5107 v_U8_t macLoop;
5108
5109 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
5110 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
5111 if(status != VOS_STATUS_SUCCESS)
5112 {
5113 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
5114 return VOS_STATUS_E_FAILURE;
5115 }
5116
5117 if (itemIsValid == VOS_TRUE)
5118 {
5119 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
5120 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
5121 VOS_MAX_CONCURRENCY_PERSONA);
5122 if(status != VOS_STATUS_SUCCESS)
5123 {
5124 /* Get MAC from NV fail, not update CFG info
5125 * INI MAC value will be used for MAC setting */
5126 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
5127 return VOS_STATUS_E_FAILURE;
5128 }
5129
5130 /* If first MAC is not valid, treat all others are not valid
5131 * Then all MACs will be got from ini file */
5132 if(vos_is_macaddr_zero(&macFromNV[0]))
5133 {
5134 /* MAC address in NV file is not configured yet */
5135 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5136 return VOS_STATUS_E_INVAL;
5137 }
5138
5139 /* Get MAC address from NV, update CFG info */
5140 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5141 {
5142 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5143 {
5144 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5145 /* This MAC is not valid, skip it
5146 * This MAC will be got from ini file */
5147 }
5148 else
5149 {
5150 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5151 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5152 VOS_MAC_ADDR_SIZE);
5153 }
5154 }
5155 }
5156 else
5157 {
5158 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5159 return VOS_STATUS_E_FAILURE;
5160 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005161
Jeff Johnson295189b2012-06-20 16:38:30 -07005162
5163 return VOS_STATUS_SUCCESS;
5164}
5165
5166/**---------------------------------------------------------------------------
5167
5168 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5169
5170 \param - pAdapter - Pointer to the HDD
5171
5172 \return - None
5173
5174 --------------------------------------------------------------------------*/
5175VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5176{
5177 eHalStatus halStatus;
5178 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305179 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07005180
Jeff Johnson295189b2012-06-20 16:38:30 -07005181
5182 // Send ready indication to the HDD. This will kick off the MAC
5183 // into a 'running' state and should kick off an initial scan.
5184 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5185 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5186 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305187 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005188 "code %08d [x%08x]",__func__, halStatus, halStatus );
5189 return VOS_STATUS_E_FAILURE;
5190 }
5191
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305192 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07005193 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5194 // And RIVA will crash
5195 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5196 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305197 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
5198 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
5199
5200
Jeff Johnson295189b2012-06-20 16:38:30 -07005201 return VOS_STATUS_SUCCESS;
5202}
5203
Jeff Johnson295189b2012-06-20 16:38:30 -07005204/* wake lock APIs for HDD */
5205void hdd_prevent_suspend(void)
5206{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005207#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005208 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005209#else
5210 wcnss_prevent_suspend();
5211#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005212}
5213
5214void hdd_allow_suspend(void)
5215{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005216#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005217 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005218#else
5219 wcnss_allow_suspend();
5220#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005221}
5222
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005223void hdd_allow_suspend_timeout(v_U32_t timeout)
5224{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005225#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005226 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005227#else
5228 /* Do nothing as there is no API in wcnss for timeout*/
5229#endif
5230}
5231
Jeff Johnson295189b2012-06-20 16:38:30 -07005232/**---------------------------------------------------------------------------
5233
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005234 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5235 information between Host and Riva
5236
5237 This function gets reported version of FW
5238 It also finds the version of Riva headers used to compile the host
5239 It compares the above two and prints a warning if they are different
5240 It gets the SW and HW version string
5241 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5242 indicating the features they support through a bitmap
5243
5244 \param - pHddCtx - Pointer to HDD context
5245
5246 \return - void
5247
5248 --------------------------------------------------------------------------*/
5249
5250void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5251{
5252
5253 tSirVersionType versionCompiled;
5254 tSirVersionType versionReported;
5255 tSirVersionString versionString;
5256 tANI_U8 fwFeatCapsMsgSupported = 0;
5257 VOS_STATUS vstatus;
5258
5259 /* retrieve and display WCNSS version information */
5260 do {
5261
5262 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5263 &versionCompiled);
5264 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5265 {
5266 hddLog(VOS_TRACE_LEVEL_FATAL,
5267 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005268 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005269 break;
5270 }
5271
5272 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5273 &versionReported);
5274 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5275 {
5276 hddLog(VOS_TRACE_LEVEL_FATAL,
5277 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005278 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005279 break;
5280 }
5281
5282 if ((versionCompiled.major != versionReported.major) ||
5283 (versionCompiled.minor != versionReported.minor) ||
5284 (versionCompiled.version != versionReported.version) ||
5285 (versionCompiled.revision != versionReported.revision))
5286 {
5287 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5288 "Host expected %u.%u.%u.%u\n",
5289 WLAN_MODULE_NAME,
5290 (int)versionReported.major,
5291 (int)versionReported.minor,
5292 (int)versionReported.version,
5293 (int)versionReported.revision,
5294 (int)versionCompiled.major,
5295 (int)versionCompiled.minor,
5296 (int)versionCompiled.version,
5297 (int)versionCompiled.revision);
5298 }
5299 else
5300 {
5301 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5302 WLAN_MODULE_NAME,
5303 (int)versionReported.major,
5304 (int)versionReported.minor,
5305 (int)versionReported.version,
5306 (int)versionReported.revision);
5307 }
5308
5309 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5310 versionString,
5311 sizeof(versionString));
5312 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5313 {
5314 hddLog(VOS_TRACE_LEVEL_FATAL,
5315 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005316 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005317 break;
5318 }
5319
5320 pr_info("%s: WCNSS software version %s\n",
5321 WLAN_MODULE_NAME, versionString);
5322
5323 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5324 versionString,
5325 sizeof(versionString));
5326 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5327 {
5328 hddLog(VOS_TRACE_LEVEL_FATAL,
5329 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005330 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005331 break;
5332 }
5333
5334 pr_info("%s: WCNSS hardware version %s\n",
5335 WLAN_MODULE_NAME, versionString);
5336
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005337 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5338 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005339 send the message only if it the riva is 1.1
5340 minor numbers for different riva branches:
5341 0 -> (1.0)Mainline Build
5342 1 -> (1.1)Mainline Build
5343 2->(1.04) Stability Build
5344 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005345 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005346 ((versionReported.minor>=1) && (versionReported.version>=1)))
5347 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5348 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005349
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005350 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005351 {
5352#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5353 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5354 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5355#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005356 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005357 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005358
5359 } while (0);
5360
5361}
5362
5363/**---------------------------------------------------------------------------
5364
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305365 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
5366
5367 \param - pHddCtx - Pointer to the hdd context
5368
5369 \return - true if hardware supports 5GHz
5370
5371 --------------------------------------------------------------------------*/
5372static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
5373{
5374 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
5375 * then hardware support 5Ghz.
5376 */
5377 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
5378 {
5379 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
5380 return true;
5381 }
5382 else
5383 {
5384 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
5385 __func__);
5386 return false;
5387 }
5388}
5389
5390
5391/**---------------------------------------------------------------------------
5392
Jeff Johnson295189b2012-06-20 16:38:30 -07005393 \brief hdd_wlan_startup() - HDD init function
5394
5395 This is the driver startup code executed once a WLAN device has been detected
5396
5397 \param - dev - Pointer to the underlying device
5398
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005399 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005400
5401 --------------------------------------------------------------------------*/
5402
5403int hdd_wlan_startup(struct device *dev )
5404{
5405 VOS_STATUS status;
5406 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005407 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005408 hdd_context_t *pHddCtx = NULL;
5409 v_CONTEXT_t pVosContext= NULL;
5410#ifdef WLAN_BTAMP_FEATURE
5411 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5412 WLANBAP_ConfigType btAmpConfig;
5413 hdd_config_t *pConfig;
5414#endif
5415 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005416 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005417
5418 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005419 /*
5420 * cfg80211: wiphy allocation
5421 */
5422 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
5423
5424 if(wiphy == NULL)
5425 {
5426 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005427 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005428 }
5429
5430 pHddCtx = wiphy_priv(wiphy);
5431
Jeff Johnson295189b2012-06-20 16:38:30 -07005432 //Initialize the adapter context to zeros.
5433 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5434
Jeff Johnson295189b2012-06-20 16:38:30 -07005435 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005436 hdd_prevent_suspend();
5437 pHddCtx->isLoadUnloadInProgress = TRUE;
5438
5439 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5440
5441 /*Get vos context here bcoz vos_open requires it*/
5442 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5443
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005444 if(pVosContext == NULL)
5445 {
5446 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5447 goto err_free_hdd_context;
5448 }
5449
Jeff Johnson295189b2012-06-20 16:38:30 -07005450 //Save the Global VOSS context in adapter context for future.
5451 pHddCtx->pvosContext = pVosContext;
5452
5453 //Save the adapter context in global context for future.
5454 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5455
Jeff Johnson295189b2012-06-20 16:38:30 -07005456 pHddCtx->parent_dev = dev;
5457
5458 init_completion(&pHddCtx->full_pwr_comp_var);
5459 init_completion(&pHddCtx->standby_comp_var);
5460 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005461 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005462 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005463
5464 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5465
5466 // Load all config first as TL config is needed during vos_open
5467 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5468 if(pHddCtx->cfg_ini == NULL)
5469 {
5470 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5471 goto err_free_hdd_context;
5472 }
5473
5474 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5475
5476 // Read and parse the qcom_cfg.ini file
5477 status = hdd_parse_config_ini( pHddCtx );
5478 if ( VOS_STATUS_SUCCESS != status )
5479 {
5480 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5481 __func__, WLAN_INI_FILE);
5482 goto err_config;
5483 }
5484
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05305485 /* INI has been read, initialise the configuredMcastBcastFilter with
5486 * INI value as this will serve as the default value
5487 */
5488 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
5489 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
5490 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305491
5492 if (false == hdd_is_5g_supported(pHddCtx))
5493 {
5494 //5Ghz is not supported.
5495 if (1 != pHddCtx->cfg_ini->nBandCapability)
5496 {
5497 hddLog(VOS_TRACE_LEVEL_INFO,
5498 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
5499 pHddCtx->cfg_ini->nBandCapability = 1;
5500 }
5501 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005502 /*
5503 * cfg80211: Initialization and registration ...
5504 */
5505 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
5506 {
5507 hddLog(VOS_TRACE_LEVEL_FATAL,
5508 "%s: wlan_hdd_cfg80211_register return failure", __func__);
5509 goto err_wiphy_reg;
5510 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005511
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005512 // Update VOS trace levels based upon the cfg.ini
5513 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5514 pHddCtx->cfg_ini->vosTraceEnableBAP);
5515 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5516 pHddCtx->cfg_ini->vosTraceEnableTL);
5517 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5518 pHddCtx->cfg_ini->vosTraceEnableWDI);
5519 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5520 pHddCtx->cfg_ini->vosTraceEnableHDD);
5521 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5522 pHddCtx->cfg_ini->vosTraceEnableSME);
5523 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5524 pHddCtx->cfg_ini->vosTraceEnablePE);
5525 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5526 pHddCtx->cfg_ini->vosTraceEnableWDA);
5527 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5528 pHddCtx->cfg_ini->vosTraceEnableSYS);
5529 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5530 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005531 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5532 pHddCtx->cfg_ini->vosTraceEnableSAP);
5533 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5534 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005535
Jeff Johnson295189b2012-06-20 16:38:30 -07005536 // Update WDI trace levels based upon the cfg.ini
5537 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5538 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5539 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5540 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5541 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5542 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5543 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5544 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005545
Jeff Johnson88ba7742013-02-27 14:36:02 -08005546 if (VOS_FTM_MODE == hdd_get_conparam())
5547 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005548 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5549 {
5550 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5551 goto err_free_hdd_context;
5552 }
5553 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5554 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005555 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005556
Jeff Johnson88ba7742013-02-27 14:36:02 -08005557 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005558 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5559 {
5560 status = vos_watchdog_open(pVosContext,
5561 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5562
5563 if(!VOS_IS_STATUS_SUCCESS( status ))
5564 {
5565 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005566 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005567 }
5568 }
5569
5570 pHddCtx->isLogpInProgress = FALSE;
5571 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5572
Jeff Johnson295189b2012-06-20 16:38:30 -07005573 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5574 if(!VOS_IS_STATUS_SUCCESS(status))
5575 {
5576 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005577 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005578 }
5579
Jeff Johnson295189b2012-06-20 16:38:30 -07005580 status = vos_open( &pVosContext, 0);
5581 if ( !VOS_IS_STATUS_SUCCESS( status ))
5582 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005583 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5584 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005585 }
5586
Jeff Johnson295189b2012-06-20 16:38:30 -07005587 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5588
5589 if ( NULL == pHddCtx->hHal )
5590 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005591 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005592 goto err_vosclose;
5593 }
5594
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005595 status = vos_preStart( pHddCtx->pvosContext );
5596 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5597 {
5598 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5599 goto err_vosclose;
5600 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005601
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005602 /* Note that the vos_preStart() sequence triggers the cfg download.
5603 The cfg download must occur before we update the SME config
5604 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005605 status = hdd_set_sme_config( pHddCtx );
5606
5607 if ( VOS_STATUS_SUCCESS != status )
5608 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005609 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5610 goto err_vosclose;
5611 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005612
5613 //Initialize the WMM module
5614 status = hdd_wmm_init(pHddCtx);
5615 if (!VOS_IS_STATUS_SUCCESS(status))
5616 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005617 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005618 goto err_vosclose;
5619 }
5620
Jeff Johnson295189b2012-06-20 16:38:30 -07005621 /* In the integrated architecture we update the configuration from
5622 the INI file and from NV before vOSS has been started so that
5623 the final contents are available to send down to the cCPU */
5624
5625 // Apply the cfg.ini to cfg.dat
5626 if (FALSE == hdd_update_config_dat(pHddCtx))
5627 {
5628 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5629 goto err_vosclose;
5630 }
5631
5632 // Apply the NV to cfg.dat
5633 /* Prima Update MAC address only at here */
5634 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5635 {
5636#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5637 /* There was not a valid set of MAC Addresses in NV. See if the
5638 default addresses were modified by the cfg.ini settings. If so,
5639 we'll use them, but if not, we'll autogenerate a set of MAC
5640 addresses based upon the device serial number */
5641
5642 static const v_MACADDR_t default_address =
5643 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5644 unsigned int serialno;
5645 int i;
5646
5647 serialno = wcnss_get_serial_number();
5648 if ((0 != serialno) &&
5649 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5650 sizeof(default_address))))
5651 {
5652 /* cfg.ini has the default address, invoke autogen logic */
5653
5654 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5655 bytes of the serial number that can be used to generate
5656 the other 3 bytes of the MAC address. Mask off all but
5657 the lower 3 bytes (this will also make sure we don't
5658 overflow in the next step) */
5659 serialno &= 0x00FFFFFF;
5660
5661 /* we need a unique address for each session */
5662 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5663
5664 /* autogen all addresses */
5665 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5666 {
5667 /* start with the entire default address */
5668 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5669 /* then replace the lower 3 bytes */
5670 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5671 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5672 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5673
5674 serialno++;
5675 }
5676
5677 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5678 MAC_ADDRESS_STR,
5679 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5680 }
5681 else
5682#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5683 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005684 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005685 "%s: Invalid MAC address in NV, using MAC from ini file "
5686 MAC_ADDRESS_STR, __func__,
5687 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5688 }
5689 }
5690 {
5691 eHalStatus halStatus;
5692 // Set the MAC Address
5693 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5694 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5695 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5696 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5697
5698 if (!HAL_STATUS_SUCCESS( halStatus ))
5699 {
5700 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5701 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005702 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005703 }
5704 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005705
5706 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5707 Note: Firmware image will be read and downloaded inside vos_start API */
5708 status = vos_start( pHddCtx->pvosContext );
5709 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5710 {
5711 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5712 goto err_vosclose;
5713 }
5714
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005715 /* Exchange capability info between Host and FW and also get versioning info from FW */
5716 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005717
5718 status = hdd_post_voss_start_config( pHddCtx );
5719 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5720 {
5721 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5722 __func__);
5723 goto err_vosstop;
5724 }
5725
Jeff Johnson295189b2012-06-20 16:38:30 -07005726 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5727 {
5728 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5729 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5730 }
5731 else
5732 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005733 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5734 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5735 if (pAdapter != NULL)
5736 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305737 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005738 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305739 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5740 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5741 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005742
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305743 /* Generate the P2P Device Address. This consists of the device's
5744 * primary MAC address with the locally administered bit set.
5745 */
5746 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005747 }
5748 else
5749 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305750 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5751 if (p2p_dev_addr != NULL)
5752 {
5753 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5754 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5755 }
5756 else
5757 {
5758 hddLog(VOS_TRACE_LEVEL_FATAL,
5759 "%s: Failed to allocate mac_address for p2p_device",
5760 __func__);
5761 goto err_close_adapter;
5762 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005763 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005764
5765 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5766 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5767 if ( NULL == pP2pAdapter )
5768 {
5769 hddLog(VOS_TRACE_LEVEL_FATAL,
5770 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005771 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005772 goto err_close_adapter;
5773 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005774 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005775 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005776
5777 if( pAdapter == NULL )
5778 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005779 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5780 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005781 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005782
Jeff Johnson295189b2012-06-20 16:38:30 -07005783#ifdef WLAN_BTAMP_FEATURE
5784 vStatus = WLANBAP_Open(pVosContext);
5785 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5786 {
5787 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5788 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005789 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005790 }
5791
5792 vStatus = BSL_Init(pVosContext);
5793 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5794 {
5795 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5796 "%s: Failed to Init BSL",__func__);
5797 goto err_bap_close;
5798 }
5799 vStatus = WLANBAP_Start(pVosContext);
5800 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5801 {
5802 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5803 "%s: Failed to start TL",__func__);
5804 goto err_bap_close;
5805 }
5806
5807 pConfig = pHddCtx->cfg_ini;
5808 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5809 status = WLANBAP_SetConfig(&btAmpConfig);
5810
5811#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005812
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005813#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5814 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5815 {
5816 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5817 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5818 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5819 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5820 }
5821#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005822#ifdef FEATURE_WLAN_SCAN_PNO
5823 /*SME must send channel update configuration to RIVA*/
5824 sme_UpdateChannelConfig(pHddCtx->hHal);
5825#endif
5826
Jeff Johnson295189b2012-06-20 16:38:30 -07005827 /* Register with platform driver as client for Suspend/Resume */
5828 status = hddRegisterPmOps(pHddCtx);
5829 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5830 {
5831 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5832#ifdef WLAN_BTAMP_FEATURE
5833 goto err_bap_stop;
5834#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005835 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005836#endif //WLAN_BTAMP_FEATURE
5837 }
5838
5839 /* Register TM level change handler function to the platform */
5840 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5841 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5842 {
5843 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5844 goto err_unregister_pmops;
5845 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005846
5847 /* register for riva power on lock to platform driver */
5848 if (req_riva_power_on_lock("wlan"))
5849 {
5850 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5851 __func__);
5852 goto err_unregister_pmops;
5853 }
5854
Jeff Johnson295189b2012-06-20 16:38:30 -07005855 // register net device notifier for device change notification
5856 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5857
5858 if(ret < 0)
5859 {
5860 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5861 goto err_free_power_on_lock;
5862 }
5863
5864 //Initialize the nlink service
5865 if(nl_srv_init() != 0)
5866 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305867 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005868 goto err_reg_netdev;
5869 }
5870
5871 //Initialize the BTC service
5872 if(btc_activate_service(pHddCtx) != 0)
5873 {
5874 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5875 goto err_nl_srv;
5876 }
5877
5878#ifdef PTT_SOCK_SVC_ENABLE
5879 //Initialize the PTT service
5880 if(ptt_sock_activate_svc(pHddCtx) != 0)
5881 {
5882 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5883 goto err_nl_srv;
5884 }
5885#endif
5886
Jeff Johnson295189b2012-06-20 16:38:30 -07005887 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005888 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005889 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005890 /* Action frame registered in one adapter which will
5891 * applicable to all interfaces
5892 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005893 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005894 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005895
5896 mutex_init(&pHddCtx->sap_lock);
5897
5898 pHddCtx->isLoadUnloadInProgress = FALSE;
5899
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005900#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005901#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5902 /* Initialize the wake lcok */
5903 wake_lock_init(&pHddCtx->rx_wake_lock,
5904 WAKE_LOCK_SUSPEND,
5905 "qcom_rx_wakelock");
5906#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005907 /* Initialize the wake lcok */
5908 wake_lock_init(&pHddCtx->sap_wake_lock,
5909 WAKE_LOCK_SUSPEND,
5910 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005911#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005912
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005913 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5914 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005915
5916 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5917 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005918
5919 // Initialize the restart logic
5920 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305921
Jeff Johnson295189b2012-06-20 16:38:30 -07005922 goto success;
5923
5924err_nl_srv:
5925 nl_srv_exit();
5926
5927err_reg_netdev:
5928 unregister_netdevice_notifier(&hdd_netdev_notifier);
5929
5930err_free_power_on_lock:
5931 free_riva_power_on_lock("wlan");
5932
5933err_unregister_pmops:
5934 hddDevTmUnregisterNotifyCallback(pHddCtx);
5935 hddDeregisterPmOps(pHddCtx);
5936
5937#ifdef WLAN_BTAMP_FEATURE
5938err_bap_stop:
5939 WLANBAP_Stop(pVosContext);
5940#endif
5941
5942#ifdef WLAN_BTAMP_FEATURE
5943err_bap_close:
5944 WLANBAP_Close(pVosContext);
5945#endif
5946
Jeff Johnson295189b2012-06-20 16:38:30 -07005947err_close_adapter:
5948 hdd_close_all_adapters( pHddCtx );
5949
5950err_vosstop:
5951 vos_stop(pVosContext);
5952
5953err_vosclose:
5954 status = vos_sched_close( pVosContext );
5955 if (!VOS_IS_STATUS_SUCCESS(status)) {
5956 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5957 "%s: Failed to close VOSS Scheduler", __func__);
5958 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5959 }
5960 vos_close(pVosContext );
5961
Jeff Johnson295189b2012-06-20 16:38:30 -07005962err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005963 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005964
5965err_wdclose:
5966 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5967 vos_watchdog_close(pVosContext);
5968
Jeff Johnson295189b2012-06-20 16:38:30 -07005969err_wiphy_reg:
5970 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005971
5972err_config:
5973 kfree(pHddCtx->cfg_ini);
5974 pHddCtx->cfg_ini= NULL;
5975
5976err_free_hdd_context:
5977 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005978 wiphy_free(wiphy) ;
5979 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005980 VOS_BUG(1);
5981
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005982 if (hdd_is_ssr_required())
5983 {
5984 /* WDI timeout had happened during load, so SSR is needed here */
5985 subsystem_restart("wcnss");
5986 msleep(5000);
5987 }
5988 hdd_set_ssr_required (VOS_FALSE);
5989
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005990 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005991
5992success:
5993 EXIT();
5994 return 0;
5995}
5996
5997/**---------------------------------------------------------------------------
5998
Jeff Johnson32d95a32012-09-10 13:15:23 -07005999 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07006000
Jeff Johnson32d95a32012-09-10 13:15:23 -07006001 This is the driver entry point - called in different timeline depending
6002 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07006003
6004 \param - None
6005
6006 \return - 0 for success, non zero for failure
6007
6008 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07006009static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006010{
6011 VOS_STATUS status;
6012 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006013 struct device *dev = NULL;
6014 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006015#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6016 int max_retries = 0;
6017#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006018
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306019#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6020 vos_wconn_trace_init();
6021#endif
6022
Jeff Johnson295189b2012-06-20 16:38:30 -07006023 ENTER();
6024
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006025#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006026 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07006027#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006028
6029 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
6030 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
6031
6032 //Power Up Libra WLAN card first if not already powered up
6033 status = vos_chipPowerUp(NULL,NULL,NULL);
6034 if (!VOS_IS_STATUS_SUCCESS(status))
6035 {
6036 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
6037 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006038 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006039 }
6040
Jeff Johnson295189b2012-06-20 16:38:30 -07006041#ifdef ANI_BUS_TYPE_PCI
6042
6043 dev = wcnss_wlan_get_device();
6044
6045#endif // ANI_BUS_TYPE_PCI
6046
6047#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006048
6049#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6050 /* wait until WCNSS driver downloads NV */
6051 while (!wcnss_device_ready() && 5 >= ++max_retries) {
6052 msleep(1000);
6053 }
6054 if (max_retries >= 5) {
6055 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
6056 return -ENODEV;
6057 }
6058#endif
6059
Jeff Johnson295189b2012-06-20 16:38:30 -07006060 dev = wcnss_wlan_get_device();
6061#endif // ANI_BUS_TYPE_PLATFORM
6062
6063
6064 do {
6065 if (NULL == dev) {
6066 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
6067 ret_status = -1;
6068 break;
6069 }
6070
6071#ifdef MEMORY_DEBUG
6072 vos_mem_init();
6073#endif
6074
6075#ifdef TIMER_MANAGER
6076 vos_timer_manager_init();
6077#endif
6078
6079 /* Preopen VOSS so that it is ready to start at least SAL */
6080 status = vos_preOpen(&pVosContext);
6081
6082 if (!VOS_IS_STATUS_SUCCESS(status))
6083 {
6084 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
6085 ret_status = -1;
6086 break;
6087 }
6088
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006089#ifndef MODULE
6090 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
6091 */
6092 hdd_set_conparam((v_UINT_t)con_mode);
6093#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006094
6095 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006096 if (hdd_wlan_startup(dev))
6097 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006098 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006099 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006100 vos_preClose( &pVosContext );
6101 ret_status = -1;
6102 break;
6103 }
6104
6105 /* Cancel the vote for XO Core ON
6106 * This is done here for safety purposes in case we re-initialize without turning
6107 * it OFF in any error scenario.
6108 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006109 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07006110 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006111 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07006112 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6113 {
6114 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
6115 " Power consumed will be high\n");
6116 }
6117 } while (0);
6118
6119 if (0 != ret_status)
6120 {
6121 //Assert Deep sleep signal now to put Libra HW in lowest power state
6122 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6123 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
6124
6125 //Vote off any PMIC voltage supplies
6126 vos_chipPowerDown(NULL, NULL, NULL);
6127#ifdef TIMER_MANAGER
6128 vos_timer_exit();
6129#endif
6130#ifdef MEMORY_DEBUG
6131 vos_mem_exit();
6132#endif
6133
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006134#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006135 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006136#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006137 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
6138 }
6139 else
6140 {
6141 //Send WLAN UP indication to Nlink Service
6142 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
6143
6144 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
6145
6146 }
6147
6148 EXIT();
6149
6150 return ret_status;
6151}
6152
Jeff Johnson32d95a32012-09-10 13:15:23 -07006153/**---------------------------------------------------------------------------
6154
6155 \brief hdd_module_init() - Init Function
6156
6157 This is the driver entry point (invoked when module is loaded using insmod)
6158
6159 \param - None
6160
6161 \return - 0 for success, non zero for failure
6162
6163 --------------------------------------------------------------------------*/
6164#ifdef MODULE
6165static int __init hdd_module_init ( void)
6166{
6167 return hdd_driver_init();
6168}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006169#else /* #ifdef MODULE */
6170static int __init hdd_module_init ( void)
6171{
6172 /* Driver initialization is delayed to fwpath_changed_handler */
6173 return 0;
6174}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006175#endif /* #ifdef MODULE */
6176
Jeff Johnson295189b2012-06-20 16:38:30 -07006177
6178/**---------------------------------------------------------------------------
6179
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006180 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07006181
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006182 This is the driver exit point (invoked when module is unloaded using rmmod
6183 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07006184
6185 \param - None
6186
6187 \return - None
6188
6189 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006190static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006191{
6192 hdd_context_t *pHddCtx = NULL;
6193 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006194 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006195
6196 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6197
6198 //Get the global vos context
6199 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6200
6201 if(!pVosContext)
6202 {
6203 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6204 goto done;
6205 }
6206
6207 //Get the HDD context.
6208 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6209
6210 if(!pHddCtx)
6211 {
6212 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6213 }
6214 else
6215 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006216 while(isWDresetInProgress()) {
6217 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6218 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07006219 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006220
6221 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
6222 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6223 "%s:SSR never completed, fatal error", __func__);
6224 VOS_BUG(0);
6225 }
6226 }
6227
Jeff Johnson295189b2012-06-20 16:38:30 -07006228
6229 pHddCtx->isLoadUnloadInProgress = TRUE;
6230 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6231
6232 //Do all the cleanup before deregistering the driver
6233 hdd_wlan_exit(pHddCtx);
6234 }
6235
Jeff Johnson295189b2012-06-20 16:38:30 -07006236 vos_preClose( &pVosContext );
6237
6238#ifdef TIMER_MANAGER
6239 vos_timer_exit();
6240#endif
6241#ifdef MEMORY_DEBUG
6242 vos_mem_exit();
6243#endif
6244
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306245#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6246 vos_wconn_trace_exit();
6247#endif
6248
Jeff Johnson295189b2012-06-20 16:38:30 -07006249done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006250#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006251 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006252#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006253 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6254}
6255
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006256/**---------------------------------------------------------------------------
6257
6258 \brief hdd_module_exit() - Exit function
6259
6260 This is the driver exit point (invoked when module is unloaded using rmmod)
6261
6262 \param - None
6263
6264 \return - None
6265
6266 --------------------------------------------------------------------------*/
6267static void __exit hdd_module_exit(void)
6268{
6269 hdd_driver_exit();
6270}
6271
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006272#ifdef MODULE
6273static int fwpath_changed_handler(const char *kmessage,
6274 struct kernel_param *kp)
6275{
Jeff Johnson76052702013-04-16 13:55:05 -07006276 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006277}
6278
6279static int con_mode_handler(const char *kmessage,
6280 struct kernel_param *kp)
6281{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006282 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006283}
6284#else /* #ifdef MODULE */
6285/**---------------------------------------------------------------------------
6286
Jeff Johnson76052702013-04-16 13:55:05 -07006287 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006288
Jeff Johnson76052702013-04-16 13:55:05 -07006289 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006290 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006291 - invoked when module parameter fwpath is modified from userspace to signal
6292 initializing the WLAN driver or when con_mode is modified from userspace
6293 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006294
6295 \return - 0 for success, non zero for failure
6296
6297 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006298static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006299{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006300 int ret_status;
6301
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006302 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006303 ret_status = hdd_driver_init();
6304 wlan_hdd_inited = ret_status ? 0 : 1;
6305 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006306 }
6307
6308 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006309
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006310 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006311
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006312 ret_status = hdd_driver_init();
6313 wlan_hdd_inited = ret_status ? 0 : 1;
6314 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006315}
6316
Jeff Johnson295189b2012-06-20 16:38:30 -07006317/**---------------------------------------------------------------------------
6318
Jeff Johnson76052702013-04-16 13:55:05 -07006319 \brief fwpath_changed_handler() - Handler Function
6320
6321 Handle changes to the fwpath parameter
6322
6323 \return - 0 for success, non zero for failure
6324
6325 --------------------------------------------------------------------------*/
6326static int fwpath_changed_handler(const char *kmessage,
6327 struct kernel_param *kp)
6328{
6329 int ret;
6330
6331 ret = param_set_copystring(kmessage, kp);
6332 if (0 == ret)
6333 ret = kickstart_driver();
6334 return ret;
6335}
6336
6337/**---------------------------------------------------------------------------
6338
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006339 \brief con_mode_handler() -
6340
6341 Handler function for module param con_mode when it is changed by userspace
6342 Dynamically linked - do nothing
6343 Statically linked - exit and init driver, as in rmmod and insmod
6344
Jeff Johnson76052702013-04-16 13:55:05 -07006345 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006346
Jeff Johnson76052702013-04-16 13:55:05 -07006347 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006348
6349 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006350static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006351{
Jeff Johnson76052702013-04-16 13:55:05 -07006352 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006353
Jeff Johnson76052702013-04-16 13:55:05 -07006354 ret = param_set_int(kmessage, kp);
6355 if (0 == ret)
6356 ret = kickstart_driver();
6357 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006358}
6359#endif /* #ifdef MODULE */
6360
6361/**---------------------------------------------------------------------------
6362
Jeff Johnson295189b2012-06-20 16:38:30 -07006363 \brief hdd_get_conparam() -
6364
6365 This is the driver exit point (invoked when module is unloaded using rmmod)
6366
6367 \param - None
6368
6369 \return - tVOS_CON_MODE
6370
6371 --------------------------------------------------------------------------*/
6372tVOS_CON_MODE hdd_get_conparam ( void )
6373{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006374#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006375 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006376#else
6377 return (tVOS_CON_MODE)curr_con_mode;
6378#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006379}
6380void hdd_set_conparam ( v_UINT_t newParam )
6381{
6382 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006383#ifndef MODULE
6384 curr_con_mode = con_mode;
6385#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006386}
6387/**---------------------------------------------------------------------------
6388
6389 \brief hdd_softap_sta_deauth() - function
6390
6391 This to take counter measure to handle deauth req from HDD
6392
6393 \param - pAdapter - Pointer to the HDD
6394
6395 \param - enable - boolean value
6396
6397 \return - None
6398
6399 --------------------------------------------------------------------------*/
6400
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006401VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006402{
Jeff Johnson295189b2012-06-20 16:38:30 -07006403 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006404 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006405
6406 ENTER();
6407
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306408 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006409
6410 //Ignore request to deauth bcmc station
6411 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006412 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006413
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006414 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006415
6416 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006417 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006418}
6419
6420/**---------------------------------------------------------------------------
6421
6422 \brief hdd_softap_sta_disassoc() - function
6423
6424 This to take counter measure to handle deauth req from HDD
6425
6426 \param - pAdapter - Pointer to the HDD
6427
6428 \param - enable - boolean value
6429
6430 \return - None
6431
6432 --------------------------------------------------------------------------*/
6433
6434void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6435{
6436 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6437
6438 ENTER();
6439
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306440 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006441
6442 //Ignore request to disassoc bcmc station
6443 if( pDestMacAddress[0] & 0x1 )
6444 return;
6445
6446 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6447}
6448
6449void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6450{
6451 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6452
6453 ENTER();
6454
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306455 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006456
6457 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6458}
6459
Jeff Johnson295189b2012-06-20 16:38:30 -07006460/**---------------------------------------------------------------------------
6461 *
6462 * \brief hdd_get__concurrency_mode() -
6463 *
6464 *
6465 * \param - None
6466 *
6467 * \return - CONCURRENCY MODE
6468 *
6469 * --------------------------------------------------------------------------*/
6470tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6471{
6472 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6473 hdd_context_t *pHddCtx;
6474
6475 if (NULL != pVosContext)
6476 {
6477 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6478 if (NULL != pHddCtx)
6479 {
6480 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6481 }
6482 }
6483
6484 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006485 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006486 return VOS_STA;
6487}
6488
6489/* Decide whether to allow/not the apps power collapse.
6490 * Allow apps power collapse if we are in connected state.
6491 * if not, allow only if we are in IMPS */
6492v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6493{
6494 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006495 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006496 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006497 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6498 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6499 hdd_adapter_t *pAdapter = NULL;
6500 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006501 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006502
Jeff Johnson295189b2012-06-20 16:38:30 -07006503 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6504 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006505
Yathish9f22e662012-12-10 14:21:35 -08006506 concurrent_state = hdd_get_concurrency_mode();
6507
6508#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6509 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6510 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6511 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6512 return TRUE;
6513#endif
6514
Jeff Johnson295189b2012-06-20 16:38:30 -07006515 /*loop through all adapters. TBD fix for Concurrency */
6516 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6517 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6518 {
6519 pAdapter = pAdapterNode->pAdapter;
6520 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6521 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6522 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006523 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006524 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006525 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006526 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6527 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006528 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006529 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006530 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6531 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006532 return FALSE;
6533 }
6534 }
6535 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6536 pAdapterNode = pNext;
6537 }
6538 return TRUE;
6539}
6540
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006541/* Decides whether to send suspend notification to Riva
6542 * if any adapter is in BMPS; then it is required */
6543v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6544{
6545 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6546 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6547
6548 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6549 {
6550 return TRUE;
6551 }
6552 return FALSE;
6553}
6554
Jeff Johnson295189b2012-06-20 16:38:30 -07006555void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6556{
6557 switch(mode)
6558 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006559 case VOS_STA_MODE:
6560 case VOS_P2P_CLIENT_MODE:
6561 case VOS_P2P_GO_MODE:
6562 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006563 pHddCtx->concurrency_mode |= (1 << mode);
6564 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006565 break;
6566 default:
6567 break;
6568
6569 }
6570 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6571 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6572}
6573
6574
6575void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6576{
6577 switch(mode)
6578 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006579 case VOS_STA_MODE:
6580 case VOS_P2P_CLIENT_MODE:
6581 case VOS_P2P_GO_MODE:
6582 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006583 pHddCtx->no_of_sessions[mode]--;
6584 if (!(pHddCtx->no_of_sessions[mode]))
6585 pHddCtx->concurrency_mode &= (~(1 << mode));
6586 break;
6587 default:
6588 break;
6589 }
6590 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6591 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6592}
6593
Jeff Johnsone7245742012-09-05 17:12:55 -07006594/**---------------------------------------------------------------------------
6595 *
6596 * \brief wlan_hdd_restart_init
6597 *
6598 * This function initalizes restart timer/flag. An internal function.
6599 *
6600 * \param - pHddCtx
6601 *
6602 * \return - None
6603 *
6604 * --------------------------------------------------------------------------*/
6605
6606static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6607{
6608 /* Initialize */
6609 pHddCtx->hdd_restart_retries = 0;
6610 atomic_set(&pHddCtx->isRestartInProgress, 0);
6611 vos_timer_init(&pHddCtx->hdd_restart_timer,
6612 VOS_TIMER_TYPE_SW,
6613 wlan_hdd_restart_timer_cb,
6614 pHddCtx);
6615}
6616/**---------------------------------------------------------------------------
6617 *
6618 * \brief wlan_hdd_restart_deinit
6619 *
6620 * This function cleans up the resources used. An internal function.
6621 *
6622 * \param - pHddCtx
6623 *
6624 * \return - None
6625 *
6626 * --------------------------------------------------------------------------*/
6627
6628static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6629{
6630
6631 VOS_STATUS vos_status;
6632 /* Block any further calls */
6633 atomic_set(&pHddCtx->isRestartInProgress, 1);
6634 /* Cleanup */
6635 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6636 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006637 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006638 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6639 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006640 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006641
6642}
6643
6644/**---------------------------------------------------------------------------
6645 *
6646 * \brief wlan_hdd_framework_restart
6647 *
6648 * This function uses a cfg80211 API to start a framework initiated WLAN
6649 * driver module unload/load.
6650 *
6651 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6652 *
6653 *
6654 * \param - pHddCtx
6655 *
6656 * \return - VOS_STATUS_SUCCESS: Success
6657 * VOS_STATUS_E_EMPTY: Adapter is Empty
6658 * VOS_STATUS_E_NOMEM: No memory
6659
6660 * --------------------------------------------------------------------------*/
6661
6662static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6663{
6664 VOS_STATUS status = VOS_STATUS_SUCCESS;
6665 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006666 int len = (sizeof (struct ieee80211_mgmt));
6667 struct ieee80211_mgmt *mgmt = NULL;
6668
6669 /* Prepare the DEAUTH managment frame with reason code */
6670 mgmt = kzalloc(len, GFP_KERNEL);
6671 if(mgmt == NULL)
6672 {
6673 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6674 "%s: memory allocation failed (%d bytes)", __func__, len);
6675 return VOS_STATUS_E_NOMEM;
6676 }
6677 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006678
6679 /* Iterate over all adapters/devices */
6680 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6681 do
6682 {
6683 if( (status == VOS_STATUS_SUCCESS) &&
6684 pAdapterNode &&
6685 pAdapterNode->pAdapter)
6686 {
6687 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6688 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6689 pAdapterNode->pAdapter->dev->name,
6690 pAdapterNode->pAdapter->device_mode,
6691 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006692 /*
6693 * CFG80211 event to restart the driver
6694 *
6695 * 'cfg80211_send_unprot_deauth' sends a
6696 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6697 * of SME(Linux Kernel) state machine.
6698 *
6699 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6700 * the driver.
6701 *
6702 */
6703
6704 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006705 }
6706 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6707 pAdapterNode = pNext;
6708 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6709
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006710
6711 /* Free the allocated management frame */
6712 kfree(mgmt);
6713
Jeff Johnsone7245742012-09-05 17:12:55 -07006714 /* Retry until we unload or reach max count */
6715 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6716 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6717
6718 return status;
6719
6720}
6721/**---------------------------------------------------------------------------
6722 *
6723 * \brief wlan_hdd_restart_timer_cb
6724 *
6725 * Restart timer callback. An internal function.
6726 *
6727 * \param - User data:
6728 *
6729 * \return - None
6730 *
6731 * --------------------------------------------------------------------------*/
6732
6733void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6734{
6735 hdd_context_t *pHddCtx = usrDataForCallback;
6736 wlan_hdd_framework_restart(pHddCtx);
6737 return;
6738
6739}
6740
6741
6742/**---------------------------------------------------------------------------
6743 *
6744 * \brief wlan_hdd_restart_driver
6745 *
6746 * This function sends an event to supplicant to restart the WLAN driver.
6747 *
6748 * This function is called from vos_wlanRestart.
6749 *
6750 * \param - pHddCtx
6751 *
6752 * \return - VOS_STATUS_SUCCESS: Success
6753 * VOS_STATUS_E_EMPTY: Adapter is Empty
6754 * VOS_STATUS_E_ALREADY: Request already in progress
6755
6756 * --------------------------------------------------------------------------*/
6757VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6758{
6759 VOS_STATUS status = VOS_STATUS_SUCCESS;
6760
6761 /* A tight check to make sure reentrancy */
6762 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6763 {
6764 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6765 "%s: WLAN restart is already in progress", __func__);
6766
6767 return VOS_STATUS_E_ALREADY;
6768 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006769 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006770#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006771 wcnss_reset_intr();
6772#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006773
Jeff Johnsone7245742012-09-05 17:12:55 -07006774 return status;
6775}
6776
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07006777/*
6778 * API to find if there is any STA or P2P-Client is connected
6779 */
6780VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
6781{
6782 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
6783}
Jeff Johnsone7245742012-09-05 17:12:55 -07006784
Jeff Johnson295189b2012-06-20 16:38:30 -07006785//Register the module init/exit functions
6786module_init(hdd_module_init);
6787module_exit(hdd_module_exit);
6788
6789MODULE_LICENSE("Dual BSD/GPL");
6790MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6791MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6792
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006793module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6794 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006795
Jeff Johnson76052702013-04-16 13:55:05 -07006796module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006797 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);