blob: ee259ffd754e79e9d1a9a7236e9c5a0187a64a99 [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);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800201#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700202static int hdd_netdev_notifier_call(struct notifier_block * nb,
203 unsigned long state,
204 void *ndev)
205{
206 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700207 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700208 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700209#ifdef WLAN_BTAMP_FEATURE
210 VOS_STATUS status;
211 hdd_context_t *pHddCtx;
212#endif
213
214 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700215 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700216 (strncmp(dev->name, "p2p", 3)))
217 return NOTIFY_DONE;
218
219 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700220 return NOTIFY_DONE;
221
Jeff Johnson295189b2012-06-20 16:38:30 -0700222 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700223 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700224
Jeff Johnson27cee452013-03-27 11:10:24 -0700225 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700226 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800227 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700228 VOS_ASSERT(0);
229 return NOTIFY_DONE;
230 }
231
Jeff Johnson27cee452013-03-27 11:10:24 -0700232 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
233 if (NULL == pHddCtx)
234 {
235 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
236 VOS_ASSERT(0);
237 return NOTIFY_DONE;
238 }
239
240 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
241 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700242
243 switch (state) {
244 case NETDEV_REGISTER:
245 break;
246
247 case NETDEV_UNREGISTER:
248 break;
249
250 case NETDEV_UP:
251 break;
252
253 case NETDEV_DOWN:
254 break;
255
256 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700257 if(TRUE == pAdapter->isLinkUpSvcNeeded)
258 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700259 break;
260
261 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700262 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700263 {
264 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800265 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700266 hdd_abort_mac_scan(pAdapter->pHddCtx);
267 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800268 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700269 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
270 if(!result)
271 {
272 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800273 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700274 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700275 }
276 }
277 else
278 {
279 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700280 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700281 }
282#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700283 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700284 status = WLANBAP_StopAmp();
285 if(VOS_STATUS_SUCCESS != status )
286 {
287 pHddCtx->isAmpAllowed = VOS_TRUE;
288 hddLog(VOS_TRACE_LEVEL_FATAL,
289 "%s: Failed to stop AMP", __func__);
290 }
291 else
292 {
293 //a state m/c implementation in PAL is TBD to avoid this delay
294 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700295 if ( pHddCtx->isAmpAllowed )
296 {
297 WLANBAP_DeregisterFromHCI();
298 pHddCtx->isAmpAllowed = VOS_FALSE;
299 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700300 }
301#endif //WLAN_BTAMP_FEATURE
302 break;
303
304 default:
305 break;
306 }
307
308 return NOTIFY_DONE;
309}
310
311struct notifier_block hdd_netdev_notifier = {
312 .notifier_call = hdd_netdev_notifier_call,
313};
314
315/*---------------------------------------------------------------------------
316 * Function definitions
317 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700318void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
319void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700320//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700321static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700322#ifndef MODULE
323/* current con_mode - used only for statically linked driver
324 * con_mode is changed by userspace to indicate a mode change which will
325 * result in calling the module exit and init functions. The module
326 * exit function will clean up based on the value of con_mode prior to it
327 * being changed by userspace. So curr_con_mode records the current con_mode
328 * for exit when con_mode becomes the next mode for init
329 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700330static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700331#endif
332
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800333/**---------------------------------------------------------------------------
334
335 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
336
337 Called immediately after the cfg.ini is read in order to configure
338 the desired trace levels.
339
340 \param - moduleId - module whose trace level is being configured
341 \param - bitmask - bitmask of log levels to be enabled
342
343 \return - void
344
345 --------------------------------------------------------------------------*/
346static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
347{
348 wpt_tracelevel level;
349
350 /* if the bitmask is the default value, then a bitmask was not
351 specified in cfg.ini, so leave the logging level alone (it
352 will remain at the "compiled in" default value) */
353 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
354 {
355 return;
356 }
357
358 /* a mask was specified. start by disabling all logging */
359 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
360
361 /* now cycle through the bitmask until all "set" bits are serviced */
362 level = VOS_TRACE_LEVEL_FATAL;
363 while (0 != bitmask)
364 {
365 if (bitmask & 1)
366 {
367 vos_trace_setValue(moduleId, level, 1);
368 }
369 level++;
370 bitmask >>= 1;
371 }
372}
373
374
Jeff Johnson295189b2012-06-20 16:38:30 -0700375/**---------------------------------------------------------------------------
376
377 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
378
379 Called immediately after the cfg.ini is read in order to configure
380 the desired trace levels in the WDI.
381
382 \param - moduleId - module whose trace level is being configured
383 \param - bitmask - bitmask of log levels to be enabled
384
385 \return - void
386
387 --------------------------------------------------------------------------*/
388static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
389{
390 wpt_tracelevel level;
391
392 /* if the bitmask is the default value, then a bitmask was not
393 specified in cfg.ini, so leave the logging level alone (it
394 will remain at the "compiled in" default value) */
395 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
396 {
397 return;
398 }
399
400 /* a mask was specified. start by disabling all logging */
401 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
402
403 /* now cycle through the bitmask until all "set" bits are serviced */
404 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
405 while (0 != bitmask)
406 {
407 if (bitmask & 1)
408 {
409 wpalTraceSetLevel(moduleId, level, 1);
410 }
411 level++;
412 bitmask >>= 1;
413 }
414}
Jeff Johnson295189b2012-06-20 16:38:30 -0700415
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530416void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
417{
418 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
419 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
420 hdd_config_t *cfg_param;
421 eCsrPhyMode phyMode;
422
423 if (NULL == pHddCtx)
424 {
425 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
426 "HDD Context is null !!");
427 return ;
428 }
429
430 cfg_param = pHddCtx->cfg_ini;
431
432 if (NULL == cfg_param)
433 {
434 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
435 "cfg_params not available !!");
436 return ;
437 }
438
439 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
440
441 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
442 {
443 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
444 (eCSR_DOT11_MODE_11ac == phyMode) ||
445 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
446 {
447 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
448 "Setting phymode to 11n!!");
449 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
450 }
451 }
452 else
453 {
454 /*New country Supports 11ac as well resetting value back from .ini*/
455 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
456 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
457 return ;
458 }
459
460 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
461 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
462 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
463 {
464 VOS_STATUS vosStatus;
465
466 // need to issue a disconnect to CSR.
467 INIT_COMPLETION(pAdapter->disconnect_comp_var);
468 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
469 pAdapter->sessionId,
470 eCSR_DISCONNECT_REASON_UNSPECIFIED );
471
472 if (VOS_STATUS_SUCCESS == vosStatus)
473 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
474 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
475
476 }
477}
478
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700479void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
480{
481 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
482 hdd_config_t *cfg_param;
483
484 if (NULL == pHddCtx)
485 {
486 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
487 "HDD Context is null !!");
488 return ;
489 }
490
491 cfg_param = pHddCtx->cfg_ini;
492
493 if (NULL == cfg_param)
494 {
495 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
496 "cfg_params not available !!");
497 return ;
498 }
499
500 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
501 {
502 /*New country doesn't support DFS */
503 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
504 }
505 else
506 {
507 /*New country Supports DFS as well resetting value back from .ini*/
508 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
509 }
510
511}
512
Jeff Johnson295189b2012-06-20 16:38:30 -0700513int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
514{
515 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
516 hdd_priv_data_t priv_data;
517 tANI_U8 *command = NULL;
518 int ret = 0;
519
520 if (NULL == pAdapter)
521 {
522 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700523 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700524 ret = -ENODEV;
525 goto exit;
526 }
527
Jeff Johnsone7245742012-09-05 17:12:55 -0700528 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700529 {
530 ret = -EINVAL;
531 goto exit;
532 }
533
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -0700534 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
535 {
536 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
537 "%s:LOGP in Progress. Ignore!!!", __func__);
538 ret = -EBUSY;
539 goto exit;
540 }
541
Jeff Johnson295189b2012-06-20 16:38:30 -0700542 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
543 {
544 ret = -EFAULT;
545 goto exit;
546 }
547
548 command = kmalloc(priv_data.total_len, GFP_KERNEL);
549 if (!command)
550 {
551 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700552 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700553 ret = -ENOMEM;
554 goto exit;
555 }
556
557 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
558 {
559 ret = -EFAULT;
560 goto exit;
561 }
562
563 if ((SIOCDEVPRIVATE + 1) == cmd)
564 {
565 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
566
567 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700568 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700569
570 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
571 {
572 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
573 sizeof(tSirMacAddr)))
574 {
575 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700576 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700577 ret = -EFAULT;
578 }
579 }
Amar Singhal0974e402013-02-12 14:27:46 -0800580 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700581 {
Amar Singhal0974e402013-02-12 14:27:46 -0800582 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700583 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800584
Jeff Johnson295189b2012-06-20 16:38:30 -0700585 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800586
587 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700588 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700589 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800590 "%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 -0700591 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800592 ret = hdd_setBand_helper(dev, ptr);
593 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700594 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
595 {
596 char *country_code;
597
598 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700599
600 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530601 hdd_checkandupdate_phymode(pAdapter, country_code);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700602 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
603 pAdapter, pHddCtx->pvosContext);
604 if( 0 != ret )
605 {
606 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
607 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
608
609 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700610 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800611#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
612 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
613 {
614 tANI_U8 *value = command;
615 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
616 tANI_U8 revision = 0;
617 eHalStatus status = eHAL_STATUS_SUCCESS;
618 v_REGDOMAIN_t regId;
619
620 status = hdd_parse_countryrev(value, countryCode, &revision);
621 if (eHAL_STATUS_SUCCESS != status)
622 {
623 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
624 "%s: Failed to parse country revision information", __func__);
625 ret = -EINVAL;
626 goto exit;
627 }
628
629 /* Validate country code */
630 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
631 if (eHAL_STATUS_SUCCESS != status)
632 {
633 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
634 "%s: Invalid country code %s", __func__, countryCode);
635 ret = -EINVAL;
636 goto exit;
637 }
638
639 /* Validate revision */
640 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
641 {
642 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
643 "%s: Invalid revision %d", __func__, revision);
644 ret = -EINVAL;
645 goto exit;
646 }
647
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700648 hdd_checkandupdate_dfssetting(pAdapter, countryCode);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530649 hdd_checkandupdate_phymode(pAdapter, countryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800650 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
651 pAdapter, pHddCtx->pvosContext);
652 if (0 != ret)
653 {
654 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
655 "%s: SME Change Country code fail ret=%d", __func__, ret);
656 ret = -EINVAL;
657 goto exit;
658 }
659
660 if (0 == strncmp(countryCode, "KR", 2))
661 {
662 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
663 revision);
664 if (eHAL_STATUS_SUCCESS != status)
665 {
666 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
667 "%s: Failed to build valid channel list", __func__);
668 ret = -EINVAL;
669 goto exit;
670 }
671 }
672 }
673#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700674 /*
675 command should be a string having format
676 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
677 */
Amar Singhal0974e402013-02-12 14:27:46 -0800678 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700679 {
Amar Singhal0974e402013-02-12 14:27:46 -0800680 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700681
682 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700683 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700684
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800685 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700686 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800687 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
688 {
689 int suspend = 0;
690 tANI_U8 *ptr = (tANI_U8*)command + 15;
691
692 suspend = *ptr - '0';
693 hdd_set_wlan_suspend_mode(suspend);
694 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800695#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
696 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
697 {
698 tANI_U8 *value = command;
699 int rssi = 0;
700 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
701 eHalStatus status = eHAL_STATUS_SUCCESS;
702
703 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
704 value = value + 15;
705
706 sscanf(value, "%d", &rssi);
707 lookUpThreshold = abs(rssi);
708 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
709 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
710 {
711 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
712 "Neighbor lookup threshold value %d is out of range"
713 " (Min: %d Max: %d)", lookUpThreshold,
714 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
715 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
716 ret = -EINVAL;
717 goto exit;
718 }
719
720 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
721 "%s: Received Command to Set Roam trigger"
722 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
723
724 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
725 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
726 if (eHAL_STATUS_SUCCESS != status)
727 {
728 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
729 "%s: Failed to set roam trigger, try again", __func__);
730 ret = -EPERM;
731 goto exit;
732 }
733
734 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
735 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
736 }
737 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
738 {
739 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
740 int rssi = (-1) * lookUpThreshold;
741 char extra[32];
742 tANI_U8 len = 0;
743
744 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
745 if (copy_to_user(priv_data.buf, &extra, len + 1))
746 {
747 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
748 "%s: failed to copy data to user buffer", __func__);
749 ret = -EFAULT;
750 goto exit;
751 }
752 }
753 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
754 {
755 tANI_U8 *value = command;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700756 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800757 /* input refresh period is in terms of seconds */
758 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
759 value = value + 18;
760 /* Convert the value from ascii to integer */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700761 ret = kstrtou16(value, 10, &neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800762 if (ret < 0)
763 {
764 /* If the input value is greater than max value of datatype, then also
765 kstrtou16 fails */
766 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
767 "%s: kstrtou16 failed ",
768 "Input value may be out of range[%d - %d]",
769 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700770 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
771 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800772 ret = -EINVAL;
773 goto exit;
774 }
775
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700776 neighborEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod * 1000;
777 if ((neighborEmptyScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
778 (neighborEmptyScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800779 {
780 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700781 "Neighbor empty scan results refresh period value %d is out of range"
782 " (Min: %d Max: %d)", neighborEmptyScanRefreshPeriod/1000,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700783 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
784 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800785 ret = -EINVAL;
786 goto exit;
787 }
788
789 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
790 "%s: Received Command to Set roam scan period"
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700791 " (Empty Scan refresh period) = %d", __func__, neighborEmptyScanRefreshPeriod/1000);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800792
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700793 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
794 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800795 }
796 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
797 {
798 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
799 char extra[32];
800 tANI_U8 len = 0;
801
802 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
803 /* Returned value is in units of seconds */
804 if (copy_to_user(priv_data.buf, &extra, len + 1))
805 {
806 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
807 "%s: failed to copy data to user buffer", __func__);
808 ret = -EFAULT;
809 goto exit;
810 }
811 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700812 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
813 {
814 tANI_U8 *value = command;
815 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
816 /* input refresh period is in terms of seconds */
817 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
818 value = value + 25;
819 /* Convert the value from ascii to integer */
820 ret = kstrtou16(value, 10, &neighborScanRefreshPeriod);
821 if (ret < 0)
822 {
823 /* If the input value is greater than max value of datatype, then also
824 kstrtou16 fails */
825 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
826 "%s: kstrtou16 failed ",
827 "Input value may be out of range[%d - %d]",
828 __func__,
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700829 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
830 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700831 ret = -EINVAL;
832 goto exit;
833 }
834
835 neighborScanRefreshPeriod = neighborScanRefreshPeriod * 1000;
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700836 if ((neighborScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
837 (neighborScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700838 {
839 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
840 "Neighbor scan results refresh period value %d is out of range"
841 " (Min: %d Max: %d)", neighborScanRefreshPeriod/1000,
842 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
843 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
844 ret = -EINVAL;
845 goto exit;
846 }
847
848 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
849 "%s: Received Command to Set roam scan refresh period"
850 " (Scan refresh period) = %d", __func__, neighborScanRefreshPeriod/1000);
851
852 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
853 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
854 }
855 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
856 {
857 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
858 char extra[32];
859 tANI_U8 len = 0;
860
861 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
862 /* Returned value is in units of seconds */
863 if (copy_to_user(priv_data.buf, &extra, len + 1))
864 {
865 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
866 "%s: failed to copy data to user buffer", __func__);
867 ret = -EFAULT;
868 goto exit;
869 }
870 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700871#ifdef FEATURE_WLAN_LFR
872 /* SETROAMMODE */
873 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
874 {
875 tANI_U8 *value = command;
876 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
877
878 /* Move pointer to ahead of SETROAMMODE<delimiter> */
879 value = value + SIZE_OF_SETROAMMODE + 1;
880
881 /* Convert the value from ascii to integer */
882 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
883 if (ret < 0)
884 {
885 /* If the input value is greater than max value of datatype, then also
886 kstrtou8 fails */
887 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
888 "%s: kstrtou8 failed range [%d - %d]", __func__,
889 CFG_LFR_FEATURE_ENABLED_MIN,
890 CFG_LFR_FEATURE_ENABLED_MAX);
891 ret = -EINVAL;
892 goto exit;
893 }
894 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
895 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
896 {
897 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
898 "Roam Mode value %d is out of range"
899 " (Min: %d Max: %d)", roamMode,
900 CFG_LFR_FEATURE_ENABLED_MIN,
901 CFG_LFR_FEATURE_ENABLED_MAX);
902 ret = -EINVAL;
903 goto exit;
904 }
905
906 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
907 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
908 /*
909 * Note that
910 * SETROAMMODE 0 is to enable LFR while
911 * SETROAMMODE 1 is to disable LFR, but
912 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
913 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
914 */
915 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
916 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
917 else
918 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
919
920 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
921 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
922 }
923 /* GETROAMMODE */
924 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
925 {
926 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
927 char extra[32];
928 tANI_U8 len = 0;
929
930 /*
931 * roamMode value shall be inverted because the sementics is different.
932 */
933 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
934 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
935 else
936 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
937
938 len = snprintf(extra, sizeof(extra), "%s %d", command, roamMode);
939 if (copy_to_user(priv_data.buf, &extra, len + 1))
940 {
941 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
942 "%s: failed to copy data to user buffer", __func__);
943 ret = -EFAULT;
944 goto exit;
945 }
946 }
947#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -0800948#endif
949#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
950 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
951 {
952 tANI_U8 *value = command;
953 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
954
955 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
956 value = value + 13;
957 /* Convert the value from ascii to integer */
958 ret = kstrtou8(value, 10, &roamRssiDiff);
959 if (ret < 0)
960 {
961 /* If the input value is greater than max value of datatype, then also
962 kstrtou8 fails */
963 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
964 "%s: kstrtou8 failed range [%d - %d]", __func__,
965 CFG_ROAM_RSSI_DIFF_MIN,
966 CFG_ROAM_RSSI_DIFF_MAX);
967 ret = -EINVAL;
968 goto exit;
969 }
970
971 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
972 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
973 {
974 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
975 "Roam rssi diff value %d is out of range"
976 " (Min: %d Max: %d)", roamRssiDiff,
977 CFG_ROAM_RSSI_DIFF_MIN,
978 CFG_ROAM_RSSI_DIFF_MAX);
979 ret = -EINVAL;
980 goto exit;
981 }
982
983 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
984 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
985
986 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
987 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
988 }
989 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
990 {
991 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
992 char extra[32];
993 tANI_U8 len = 0;
994
995 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
996 if (copy_to_user(priv_data.buf, &extra, len + 1))
997 {
998 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
999 "%s: failed to copy data to user buffer", __func__);
1000 ret = -EFAULT;
1001 goto exit;
1002 }
1003 }
1004#endif
1005#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1006 else if (strncmp(command, "GETBAND", 7) == 0)
1007 {
1008 int band = -1;
1009 char extra[32];
1010 tANI_U8 len = 0;
1011 hdd_getBand_helper(pHddCtx, &band);
1012
1013 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
1014 if (copy_to_user(priv_data.buf, &extra, len + 1))
1015 {
1016 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1017 "%s: failed to copy data to user buffer", __func__);
1018 ret = -EFAULT;
1019 goto exit;
1020 }
1021 }
1022 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
1023 {
1024 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
1025 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
1026 tANI_U8 revision = 0;
1027 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
1028 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
1029 char extra[32] = {0};
1030 tANI_U8 len = 0;
1031
1032 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
1033 {
1034 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1035 "%s: failed to get country code", __func__);
1036 ret = -EFAULT;
1037 goto exit;
1038 }
1039 pBuf[uBufLen] = '\0';
1040 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
1041
1042 if (0 == strncmp(pBuf, "KR", 2))
1043 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
1044 else
1045 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
1046
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 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1056 {
1057 tANI_U8 *value = command;
1058 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1059 tANI_U8 numChannels = 0;
1060 eHalStatus status = eHAL_STATUS_SUCCESS;
1061
1062 status = hdd_parse_channellist(value, ChannelList, &numChannels);
1063 if (eHAL_STATUS_SUCCESS != status)
1064 {
1065 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1066 "%s: Failed to parse channel list information", __func__);
1067 ret = -EINVAL;
1068 goto exit;
1069 }
1070
1071 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
1072 {
1073 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1074 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
1075 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
1076 ret = -EINVAL;
1077 goto exit;
1078 }
1079 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
1080 numChannels);
1081 if (eHAL_STATUS_SUCCESS != status)
1082 {
1083 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1084 "%s: Failed to update channel list information", __func__);
1085 ret = -EINVAL;
1086 goto exit;
1087 }
1088 }
1089 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
1090 {
1091 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1092 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07001093 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001094 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07001095 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001096
1097 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
1098 ChannelList, &numChannels ))
1099 {
1100 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1101 "%s: failed to get roam scan channel list", __func__);
1102 ret = -EFAULT;
1103 goto exit;
1104 }
1105 /* output channel list is of the format
1106 [Number of roam scan channels][Channel1][Channel2]... */
1107 /* copy the number of channels in the 0th index */
1108 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
1109 for (j = 0; (j < numChannels); j++)
1110 {
1111 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
1112 }
1113
1114 if (copy_to_user(priv_data.buf, &extra, len + 1))
1115 {
1116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1117 "%s: failed to copy data to user buffer", __func__);
1118 ret = -EFAULT;
1119 goto exit;
1120 }
1121 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001122 else if (strncmp(command, "GETCCXMODE", 10) == 0)
1123 {
1124 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1125 char extra[32];
1126 tANI_U8 len = 0;
1127
1128 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
1129 if (copy_to_user(priv_data.buf, &extra, len + 1))
1130 {
1131 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1132 "%s: failed to copy data to user buffer", __func__);
1133 ret = -EFAULT;
1134 goto exit;
1135 }
1136 }
1137 else if (strncmp(command, "GETOKCMODE", 10) == 0)
1138 {
1139 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
1140 char extra[32];
1141 tANI_U8 len = 0;
1142
1143 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
1144 if (copy_to_user(priv_data.buf, &extra, len + 1))
1145 {
1146 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1147 "%s: failed to copy data to user buffer", __func__);
1148 ret = -EFAULT;
1149 goto exit;
1150 }
1151 }
1152 else if (strncmp(command, "GETFASTROAM", 10) == 0)
1153 {
1154 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1155 char extra[32];
1156 tANI_U8 len = 0;
1157
1158 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
1159 if (copy_to_user(priv_data.buf, &extra, len + 1))
1160 {
1161 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1162 "%s: failed to copy data to user buffer", __func__);
1163 ret = -EFAULT;
1164 goto exit;
1165 }
1166 }
1167 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
1168 {
1169 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1170 char extra[32];
1171 tANI_U8 len = 0;
1172
1173 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
1174 if (copy_to_user(priv_data.buf, &extra, len + 1))
1175 {
1176 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1177 "%s: failed to copy data to user buffer", __func__);
1178 ret = -EFAULT;
1179 goto exit;
1180 }
1181 }
1182 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
1183 {
1184 tANI_U8 *value = command;
1185 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1186
1187 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1188 value = value + 26;
1189 /* Convert the value from ascii to integer */
1190 ret = kstrtou8(value, 10, &minTime);
1191 if (ret < 0)
1192 {
1193 /* If the input value is greater than max value of datatype, then also
1194 kstrtou8 fails */
1195 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1196 "%s: kstrtou8 failed range [%d - %d]", __func__,
1197 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1198 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1199 ret = -EINVAL;
1200 goto exit;
1201 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001202 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1203 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1204 {
1205 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1206 "scan min channel time value %d is out of range"
1207 " (Min: %d Max: %d)", minTime,
1208 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1209 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1210 ret = -EINVAL;
1211 goto exit;
1212 }
1213
1214 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1215 "%s: Received Command to change channel min time = %d", __func__, minTime);
1216
1217 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1218 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1219 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001220 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1221 {
1222 tANI_U8 *value = command;
1223 tANI_U8 channel = 0;
1224 tANI_U8 dwellTime = 0;
1225 tANI_U8 bufLen = 0;
1226 tANI_U8 *buf = NULL;
1227 tSirMacAddr targetApBssid;
1228 eHalStatus status = eHAL_STATUS_SUCCESS;
1229 struct ieee80211_channel chan;
1230 tANI_U8 finalLen = 0;
1231 tANI_U8 *finalBuf = NULL;
1232 tANI_U8 temp = 0;
1233 u64 cookie;
1234 hdd_station_ctx_t *pHddStaCtx = NULL;
1235 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1236
1237 /* if not associated, no need to send action frame */
1238 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1239 {
1240 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1241 ret = -EINVAL;
1242 goto exit;
1243 }
1244
1245 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1246 &dwellTime, &buf, &bufLen);
1247 if (eHAL_STATUS_SUCCESS != status)
1248 {
1249 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1250 "%s: Failed to parse send action frame data", __func__);
1251 ret = -EINVAL;
1252 goto exit;
1253 }
1254
1255 /* if the target bssid is different from currently associated AP,
1256 then no need to send action frame */
1257 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1258 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1259 {
1260 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1261 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001262 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001263 goto exit;
1264 }
1265
1266 /* if the channel number is different from operating channel then
1267 no need to send action frame */
1268 if (channel != pHddStaCtx->conn_info.operationChannel)
1269 {
1270 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1271 "%s: channel(%d) is different from operating channel(%d)",
1272 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1273 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001274 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001275 goto exit;
1276 }
1277 chan.center_freq = sme_ChnToFreq(channel);
1278
1279 finalLen = bufLen + 24;
1280 finalBuf = vos_mem_malloc(finalLen);
1281 if (NULL == finalBuf)
1282 {
1283 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1284 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001285 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001286 goto exit;
1287 }
1288 vos_mem_zero(finalBuf, finalLen);
1289
1290 /* Fill subtype */
1291 temp = SIR_MAC_MGMT_ACTION << 4;
1292 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1293
1294 /* Fill type */
1295 temp = SIR_MAC_MGMT_FRAME;
1296 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1297
1298 /* Fill destination address (bssid of the AP) */
1299 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1300
1301 /* Fill BSSID (STA mac address) */
1302 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1303
1304 /* Fill source address (STA mac address) */
1305 vos_mem_copy(finalBuf + 16, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1306
1307 /* Fill received buffer from 24th address */
1308 vos_mem_copy(finalBuf + 24, buf, bufLen);
1309
Jeff Johnson11c33152013-04-16 17:52:40 -07001310 /* done with the parsed buffer */
1311 vos_mem_free(buf);
1312
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001313 wlan_hdd_action( NULL, dev, &chan, 0, NL80211_CHAN_HT20,
1314 1, dwellTime, finalBuf, finalLen, 1,
1315 1, &cookie );
1316 vos_mem_free(finalBuf);
1317 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001318 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1319 {
1320 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1321 char extra[32];
1322 tANI_U8 len = 0;
1323
1324 /* value is interms of msec */
1325 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1326 if (copy_to_user(priv_data.buf, &extra, len + 1))
1327 {
1328 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1329 "%s: failed to copy data to user buffer", __func__);
1330 ret = -EFAULT;
1331 goto exit;
1332 }
1333 }
1334 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1335 {
1336 tANI_U8 *value = command;
1337 tANI_U8 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
1338
1339 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1340 value = value + 19;
1341 /* Convert the value from ascii to integer */
1342 ret = kstrtou8(value, 10, &maxTime);
1343 if (ret < 0)
1344 {
1345 /* If the input value is greater than max value of datatype, then also
1346 kstrtou8 fails */
1347 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1348 "%s: kstrtou8 failed range [%d - %d]", __func__,
1349 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1350 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1351 ret = -EINVAL;
1352 goto exit;
1353 }
1354
1355 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1356 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1357 {
1358 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1359 "lfr mode value %d is out of range"
1360 " (Min: %d Max: %d)", maxTime,
1361 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1362 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1363 ret = -EINVAL;
1364 goto exit;
1365 }
1366
1367 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1368 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1369
1370 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
1371 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1372 }
1373 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1374 {
1375 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1376 char extra[32];
1377 tANI_U8 len = 0;
1378
1379 /* value is interms of msec */
1380 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1381 if (copy_to_user(priv_data.buf, &extra, len + 1))
1382 {
1383 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1384 "%s: failed to copy data to user buffer", __func__);
1385 ret = -EFAULT;
1386 goto exit;
1387 }
1388 }
1389 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1390 {
1391 tANI_U8 *value = command;
1392 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1393
1394 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1395 value = value + 16;
1396 /* Convert the value from ascii to integer */
1397 ret = kstrtou16(value, 10, &val);
1398 if (ret < 0)
1399 {
1400 /* If the input value is greater than max value of datatype, then also
1401 kstrtou16 fails */
1402 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1403 "%s: kstrtou16 failed range [%d - %d]", __func__,
1404 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1405 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1406 ret = -EINVAL;
1407 goto exit;
1408 }
1409
1410 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1411 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1412 {
1413 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1414 "scan home time value %d is out of range"
1415 " (Min: %d Max: %d)", val,
1416 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1417 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1418 ret = -EINVAL;
1419 goto exit;
1420 }
1421
1422 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1423 "%s: Received Command to change scan home time = %d", __func__, val);
1424
1425 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1426 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1427 }
1428 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1429 {
1430 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1431 char extra[32];
1432 tANI_U8 len = 0;
1433
1434 /* value is interms of msec */
1435 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1436 if (copy_to_user(priv_data.buf, &extra, len + 1))
1437 {
1438 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1439 "%s: failed to copy data to user buffer", __func__);
1440 ret = -EFAULT;
1441 goto exit;
1442 }
1443 }
1444 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1445 {
1446 tANI_U8 *value = command;
1447 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1448
1449 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1450 value = value + 17;
1451 /* Convert the value from ascii to integer */
1452 ret = kstrtou8(value, 10, &val);
1453 if (ret < 0)
1454 {
1455 /* If the input value is greater than max value of datatype, then also
1456 kstrtou8 fails */
1457 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1458 "%s: kstrtou8 failed range [%d - %d]", __func__,
1459 CFG_ROAM_INTRA_BAND_MIN,
1460 CFG_ROAM_INTRA_BAND_MAX);
1461 ret = -EINVAL;
1462 goto exit;
1463 }
1464
1465 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1466 (val > CFG_ROAM_INTRA_BAND_MAX))
1467 {
1468 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1469 "intra band mode value %d is out of range"
1470 " (Min: %d Max: %d)", val,
1471 CFG_ROAM_INTRA_BAND_MIN,
1472 CFG_ROAM_INTRA_BAND_MAX);
1473 ret = -EINVAL;
1474 goto exit;
1475 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001476 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1477 "%s: Received Command to change intra band = %d", __func__, val);
1478
1479 pHddCtx->cfg_ini->nRoamIntraBand = val;
1480 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1481 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001482 else if (strncmp(command, "SETWESMODE", 10) == 0)
1483 {
1484 tANI_U8 *value = command;
1485 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
1486
1487 /* Move pointer to ahead of SETWESMODE<delimiter> */
1488 value = value + 11;
1489 /* Convert the value from ascii to integer */
1490 ret = kstrtou8(value, 10, &wesMode);
1491 if (ret < 0)
1492 {
1493 /* If the input value is greater than max value of datatype, then also
1494 kstrtou8 fails */
1495 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1496 "%s: kstrtou8 failed range [%d - %d]", __func__,
1497 CFG_ENABLE_WES_MODE_NAME_MIN,
1498 CFG_ENABLE_WES_MODE_NAME_MAX);
1499 ret = -EINVAL;
1500 goto exit;
1501 }
1502
1503 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
1504 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
1505 {
1506 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1507 "WES Mode value %d is out of range"
1508 " (Min: %d Max: %d)", wesMode,
1509 CFG_ENABLE_WES_MODE_NAME_MIN,
1510 CFG_ENABLE_WES_MODE_NAME_MAX);
1511 ret = -EINVAL;
1512 goto exit;
1513 }
1514 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1515 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
1516
1517 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
1518 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
1519 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001520 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1521 {
1522 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1523 char extra[32];
1524 tANI_U8 len = 0;
1525
1526 /* value is interms of msec */
1527 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1528 if (copy_to_user(priv_data.buf, &extra, len + 1))
1529 {
1530 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1531 "%s: failed to copy data to user buffer", __func__);
1532 ret = -EFAULT;
1533 goto exit;
1534 }
1535 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001536 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
1537 {
1538 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
1539 char extra[32];
1540 tANI_U8 len = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001541
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001542 len = snprintf(extra, sizeof(extra), "%s %d", command, wesMode);
1543 if (copy_to_user(priv_data.buf, &extra, len + 1))
1544 {
1545 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1546 "%s: failed to copy data to user buffer", __func__);
1547 ret = -EFAULT;
1548 goto exit;
1549 }
1550 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001551#endif
1552#ifdef FEATURE_WLAN_LFR
1553 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1554 {
1555 tANI_U8 *value = command;
1556 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1557
1558 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1559 value = value + 12;
1560 /* Convert the value from ascii to integer */
1561 ret = kstrtou8(value, 10, &lfrMode);
1562 if (ret < 0)
1563 {
1564 /* If the input value is greater than max value of datatype, then also
1565 kstrtou8 fails */
1566 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1567 "%s: kstrtou8 failed range [%d - %d]", __func__,
1568 CFG_LFR_FEATURE_ENABLED_MIN,
1569 CFG_LFR_FEATURE_ENABLED_MAX);
1570 ret = -EINVAL;
1571 goto exit;
1572 }
1573
1574 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1575 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1576 {
1577 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1578 "lfr mode value %d is out of range"
1579 " (Min: %d Max: %d)", lfrMode,
1580 CFG_LFR_FEATURE_ENABLED_MIN,
1581 CFG_LFR_FEATURE_ENABLED_MAX);
1582 ret = -EINVAL;
1583 goto exit;
1584 }
1585
1586 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1587 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1588
1589 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1590 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1591 }
1592#endif
1593#ifdef WLAN_FEATURE_VOWIFI_11R
1594 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1595 {
1596 tANI_U8 *value = command;
1597 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1598
1599 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1600 value = value + 18;
1601 /* Convert the value from ascii to integer */
1602 ret = kstrtou8(value, 10, &ft);
1603 if (ret < 0)
1604 {
1605 /* If the input value is greater than max value of datatype, then also
1606 kstrtou8 fails */
1607 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1608 "%s: kstrtou8 failed range [%d - %d]", __func__,
1609 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1610 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1611 ret = -EINVAL;
1612 goto exit;
1613 }
1614
1615 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1616 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1617 {
1618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1619 "ft mode value %d is out of range"
1620 " (Min: %d Max: %d)", ft,
1621 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1622 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1623 ret = -EINVAL;
1624 goto exit;
1625 }
1626
1627 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1628 "%s: Received Command to change ft mode = %d", __func__, ft);
1629
1630 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1631 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1632 }
1633#endif
1634#ifdef FEATURE_WLAN_CCX
1635 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1636 {
1637 tANI_U8 *value = command;
1638 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1639
1640 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1641 value = value + 11;
1642 /* Convert the value from ascii to integer */
1643 ret = kstrtou8(value, 10, &ccxMode);
1644 if (ret < 0)
1645 {
1646 /* If the input value is greater than max value of datatype, then also
1647 kstrtou8 fails */
1648 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1649 "%s: kstrtou8 failed range [%d - %d]", __func__,
1650 CFG_CCX_FEATURE_ENABLED_MIN,
1651 CFG_CCX_FEATURE_ENABLED_MAX);
1652 ret = -EINVAL;
1653 goto exit;
1654 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001655 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1656 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1657 {
1658 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1659 "Ccx mode value %d is out of range"
1660 " (Min: %d Max: %d)", ccxMode,
1661 CFG_CCX_FEATURE_ENABLED_MIN,
1662 CFG_CCX_FEATURE_ENABLED_MAX);
1663 ret = -EINVAL;
1664 goto exit;
1665 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001666 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1667 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1668
1669 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1670 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1671 }
1672#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001673 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1674 {
1675 tANI_U8 *value = command;
1676 tANI_BOOLEAN roamScanControl = 0;
1677
1678 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1679 value = value + 19;
1680 /* Convert the value from ascii to integer */
1681 ret = kstrtou8(value, 10, &roamScanControl);
1682 if (ret < 0)
1683 {
1684 /* If the input value is greater than max value of datatype, then also
1685 kstrtou8 fails */
1686 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1687 "%s: kstrtou8 failed ", __func__);
1688 ret = -EINVAL;
1689 goto exit;
1690 }
1691
1692 if (0 != roamScanControl)
1693 {
1694 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1695 "roam scan control invalid value = %d",
1696 roamScanControl);
1697 ret = -EINVAL;
1698 goto exit;
1699 }
1700 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1701 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1702
1703 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1704 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001705#ifdef FEATURE_WLAN_OKC
1706 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1707 {
1708 tANI_U8 *value = command;
1709 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1710
1711 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1712 value = value + 11;
1713 /* Convert the value from ascii to integer */
1714 ret = kstrtou8(value, 10, &okcMode);
1715 if (ret < 0)
1716 {
1717 /* If the input value is greater than max value of datatype, then also
1718 kstrtou8 fails */
1719 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1720 "%s: kstrtou8 failed range [%d - %d]", __func__,
1721 CFG_OKC_FEATURE_ENABLED_MIN,
1722 CFG_OKC_FEATURE_ENABLED_MAX);
1723 ret = -EINVAL;
1724 goto exit;
1725 }
1726
1727 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1728 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1729 {
1730 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1731 "Okc mode value %d is out of range"
1732 " (Min: %d Max: %d)", okcMode,
1733 CFG_OKC_FEATURE_ENABLED_MIN,
1734 CFG_OKC_FEATURE_ENABLED_MAX);
1735 ret = -EINVAL;
1736 goto exit;
1737 }
1738
1739 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1740 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1741
1742 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1743 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001744 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1745 {
1746 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1747 char extra[32];
1748 tANI_U8 len = 0;
1749
1750 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1751 if (copy_to_user(priv_data.buf, &extra, len + 1))
1752 {
1753 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1754 "%s: failed to copy data to user buffer", __func__);
1755 ret = -EFAULT;
1756 goto exit;
1757 }
1758 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001759#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001760 else {
1761 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
1762 __func__, command);
1763 }
1764
Jeff Johnson295189b2012-06-20 16:38:30 -07001765 }
1766exit:
1767 if (command)
1768 {
1769 kfree(command);
1770 }
1771 return ret;
1772}
1773
Srinivas Girigowdade697412013-02-14 16:31:48 -08001774#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1775void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
1776{
1777 eCsrBand band = -1;
1778 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
1779 switch (band)
1780 {
1781 case eCSR_BAND_ALL:
1782 *pBand = WLAN_HDD_UI_BAND_AUTO;
1783 break;
1784
1785 case eCSR_BAND_24:
1786 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
1787 break;
1788
1789 case eCSR_BAND_5G:
1790 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
1791 break;
1792
1793 default:
1794 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
1795 *pBand = -1;
1796 break;
1797 }
1798}
1799
1800/**---------------------------------------------------------------------------
1801
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001802 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
1803
1804 This function parses the send action frame data passed in the format
1805 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
1806
1807 \param - pValue Pointer to input country code revision
1808 \param - pTargetApBssid Pointer to target Ap bssid
1809 \param - pChannel Pointer to the Target AP channel
1810 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
1811 \param - pBuf Pointer to data
1812 \param - pBufLen Pointer to data length
1813
1814 \return - 0 for success non-zero for failure
1815
1816 --------------------------------------------------------------------------*/
1817VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
1818 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
1819{
1820 tANI_U8 *inPtr = pValue;
1821 tANI_U8 *dataEnd;
1822 int tempInt;
1823 int j = 0;
1824 int i = 0;
1825 int v = 0;
1826 tANI_U8 tempBuf[32];
1827 tANI_U8 tempByte = 0;
1828
1829 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1830 /*no argument after the command*/
1831 if (NULL == inPtr)
1832 {
1833 return -EINVAL;
1834 }
1835
1836 /*no space after the command*/
1837 else if (SPACE_ASCII_VALUE != *inPtr)
1838 {
1839 return -EINVAL;
1840 }
1841
1842 /*removing empty spaces*/
1843 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1844
1845 /*no argument followed by spaces*/
1846 if ('\0' == *inPtr)
1847 {
1848 return -EINVAL;
1849 }
1850
1851 /*getting the first argument ie the target AP bssid */
1852 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
1853 {
1854 return -EINVAL;
1855 }
1856 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
1857 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
1858 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
1859
1860 /* point to the next argument */
1861 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1862 /*no argument after the command*/
1863 if (NULL == inPtr) return -EINVAL;
1864
1865 /*removing empty spaces*/
1866 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1867
1868 /*no argument followed by spaces*/
1869 if ('\0' == *inPtr)
1870 {
1871 return -EINVAL;
1872 }
1873
1874 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07001875 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001876 v = kstrtos32(tempBuf, 10, &tempInt);
1877 if ( v < 0) return -EINVAL;
1878
1879 *pChannel = tempInt;
1880
1881 /* point to the next argument */
1882 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1883 /*no argument after the command*/
1884 if (NULL == inPtr) return -EINVAL;
1885 /*removing empty spaces*/
1886 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1887
1888 /*no argument followed by spaces*/
1889 if ('\0' == *inPtr)
1890 {
1891 return -EINVAL;
1892 }
1893
1894 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07001895 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001896 v = kstrtos32(tempBuf, 10, &tempInt);
1897 if ( v < 0) return -EINVAL;
1898
1899 *pDwellTime = tempInt;
1900
1901 /* point to the next argument */
1902 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1903 /*no argument after the command*/
1904 if (NULL == inPtr) return -EINVAL;
1905 /*removing empty spaces*/
1906 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1907
1908 /*no argument followed by spaces*/
1909 if ('\0' == *inPtr)
1910 {
1911 return -EINVAL;
1912 }
1913
1914 /* find the length of data */
1915 dataEnd = inPtr;
1916 while(('\0' != *dataEnd) )
1917 {
1918 dataEnd++;
1919 ++(*pBufLen);
1920 }
1921 if ( *pBufLen <= 0) return -EINVAL;
1922
1923 *pBuf = vos_mem_malloc(sizeof(*pBufLen));
1924 if (NULL == *pBuf)
1925 {
1926 hddLog(VOS_TRACE_LEVEL_FATAL,
1927 "%s: vos_mem_alloc failed ", __func__);
1928 return -EINVAL;
1929 }
1930
1931 /* the buffer received from the upper layer is character buffer,
1932 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
1933 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
1934 and f0 in 3rd location */
1935 for (i = 0, j = 0; j < *pBufLen; j += 2)
1936 {
1937 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
1938 (*pBuf)[i++] = tempByte;
1939 }
1940 *pBufLen = i;
1941 return VOS_STATUS_SUCCESS;
1942}
1943
1944#endif
1945/**---------------------------------------------------------------------------
1946
Srinivas Girigowdade697412013-02-14 16:31:48 -08001947 \brief hdd_parse_countryrev() - HDD Parse country code revision
1948
1949 This function parses the country code revision passed in the format
1950 SETCOUNTRYREV<space><Country code><space>revision
1951
1952 \param - pValue Pointer to input country code revision
1953 \param - pCountryCode Pointer to local output array to record country code
1954 \param - pRevision Pointer to store revision integer number
1955
1956 \return - 0 for success non-zero for failure
1957
1958 --------------------------------------------------------------------------*/
1959VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
1960{
1961 tANI_U8 *inPtr = pValue;
1962 int tempInt;
1963
1964 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1965 /*no argument after the command*/
1966 if (NULL == inPtr)
1967 {
1968 return -EINVAL;
1969 }
1970
1971 /*no space after the command*/
1972 else if (SPACE_ASCII_VALUE != *inPtr)
1973 {
1974 return -EINVAL;
1975 }
1976
1977 /*removing empty spaces*/
1978 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
1979
1980 /*no argument followed by spaces*/
1981 if ('\0' == *inPtr)
1982 {
1983 return -EINVAL;
1984 }
1985
1986 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07001987 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001988
1989 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1990 "Country code is : %s", pCountryCode);
1991
1992 /*inPtr pointing to the beginning of first space after country code */
1993 inPtr = strpbrk( inPtr, " " );
1994 /*no revision number after the country code argument */
1995 if (NULL == inPtr)
1996 {
1997 return -EINVAL;
1998 }
1999
2000 inPtr++;
2001
2002 /*removing empty space*/
2003 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2004
2005 /*no channel list after the number of channels argument and spaces*/
2006 if (0 == strncmp(pCountryCode, "KR", 2))
2007 {
2008 if ('\0' == *inPtr)
2009 {
2010 return -EINVAL;
2011 }
2012
2013 sscanf(inPtr, "%d", &tempInt);
2014 *pRevision = tempInt;
2015 }
2016 else
2017 {
2018 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2019 "Revision input is required only for Country KR");
2020 return -EINVAL;
2021 }
2022 return VOS_STATUS_SUCCESS;
2023}
2024
2025/**---------------------------------------------------------------------------
2026
2027 \brief hdd_parse_channellist() - HDD Parse channel list
2028
2029 This function parses the channel list passed in the format
2030 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002031 if the Number of channels (N) does not match with the actual number of channels passed
2032 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2033 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2034 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2035 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002036
2037 \param - pValue Pointer to input channel list
2038 \param - ChannelList Pointer to local output array to record channel list
2039 \param - pNumChannels Pointer to number of roam scan channels
2040
2041 \return - 0 for success non-zero for failure
2042
2043 --------------------------------------------------------------------------*/
2044VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2045{
2046 tANI_U8 *inPtr = pValue;
2047 int tempInt;
2048 int j = 0;
2049 int v = 0;
2050 char buf[32];
2051
2052 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2053 /*no argument after the command*/
2054 if (NULL == inPtr)
2055 {
2056 return -EINVAL;
2057 }
2058
2059 /*no space after the command*/
2060 else if (SPACE_ASCII_VALUE != *inPtr)
2061 {
2062 return -EINVAL;
2063 }
2064
2065 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002066 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002067
2068 /*no argument followed by spaces*/
2069 if ('\0' == *inPtr)
2070 {
2071 return -EINVAL;
2072 }
2073
2074 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002075 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002076 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002077 if ((v < 0) ||
2078 (tempInt <= 0) ||
2079 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2080 {
2081 return -EINVAL;
2082 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002083
2084 *pNumChannels = tempInt;
2085
2086 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2087 "Number of channels are: %d", *pNumChannels);
2088
2089 for (j = 0; j < (*pNumChannels); j++)
2090 {
2091 /*inPtr pointing to the beginning of first space after number of channels*/
2092 inPtr = strpbrk( inPtr, " " );
2093 /*no channel list after the number of channels argument*/
2094 if (NULL == inPtr)
2095 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002096 if (0 != j)
2097 {
2098 *pNumChannels = j;
2099 return VOS_STATUS_SUCCESS;
2100 }
2101 else
2102 {
2103 return -EINVAL;
2104 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002105 }
2106
2107 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002108 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002109
2110 /*no channel list after the number of channels argument and spaces*/
2111 if ( '\0' == *inPtr )
2112 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002113 if (0 != j)
2114 {
2115 *pNumChannels = j;
2116 return VOS_STATUS_SUCCESS;
2117 }
2118 else
2119 {
2120 return -EINVAL;
2121 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002122 }
2123
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002124 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002125 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002126 if ((v < 0) ||
2127 (tempInt <= 0) ||
2128 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2129 {
2130 return -EINVAL;
2131 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002132 pChannelList[j] = tempInt;
2133
2134 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2135 "Channel %d added to preferred channel list",
2136 pChannelList[j] );
2137 }
2138
Srinivas Girigowdade697412013-02-14 16:31:48 -08002139 return VOS_STATUS_SUCCESS;
2140}
2141
Jeff Johnson295189b2012-06-20 16:38:30 -07002142/**---------------------------------------------------------------------------
2143
2144 \brief hdd_open() - HDD Open function
2145
2146 This is called in response to ifconfig up
2147
2148 \param - dev Pointer to net_device structure
2149
2150 \return - 0 for success non-zero for failure
2151
2152 --------------------------------------------------------------------------*/
2153int hdd_open (struct net_device *dev)
2154{
2155 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2156 hdd_context_t *pHddCtx;
2157 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2158 VOS_STATUS status;
2159 v_BOOL_t in_standby = TRUE;
2160
2161 if (NULL == pAdapter)
2162 {
2163 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002164 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002165 return -ENODEV;
2166 }
2167
2168 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2169 if (NULL == pHddCtx)
2170 {
2171 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002172 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002173 return -ENODEV;
2174 }
2175
2176 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2177 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2178 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002179 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2180 {
2181 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302182 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002183 in_standby = FALSE;
2184 break;
2185 }
2186 else
2187 {
2188 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2189 pAdapterNode = pNext;
2190 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002191 }
2192
2193 if (TRUE == in_standby)
2194 {
2195 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2196 {
2197 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2198 "wlan out of power save", __func__);
2199 return -EINVAL;
2200 }
2201 }
2202
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002203 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002204 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2205 {
2206 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002207 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002208 /* Enable TX queues only when we are connected */
2209 netif_tx_start_all_queues(dev);
2210 }
2211
2212 return 0;
2213}
2214
2215int hdd_mon_open (struct net_device *dev)
2216{
2217 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2218
2219 if(pAdapter == NULL) {
2220 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002221 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002222 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002223 }
2224
2225 netif_start_queue(dev);
2226
2227 return 0;
2228}
2229/**---------------------------------------------------------------------------
2230
2231 \brief hdd_stop() - HDD stop function
2232
2233 This is called in response to ifconfig down
2234
2235 \param - dev Pointer to net_device structure
2236
2237 \return - 0 for success non-zero for failure
2238
2239 --------------------------------------------------------------------------*/
2240
2241int hdd_stop (struct net_device *dev)
2242{
2243 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2244 hdd_context_t *pHddCtx;
2245 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2246 VOS_STATUS status;
2247 v_BOOL_t enter_standby = TRUE;
2248
2249 ENTER();
2250
2251 if (NULL == pAdapter)
2252 {
2253 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002254 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002255 return -ENODEV;
2256 }
2257
2258 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2259 if (NULL == pHddCtx)
2260 {
2261 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002262 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002263 return -ENODEV;
2264 }
2265
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002266 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002267 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2268 netif_tx_disable(pAdapter->dev);
2269 netif_carrier_off(pAdapter->dev);
2270
2271
2272 /* SoftAP ifaces should never go in power save mode
2273 making sure same here. */
2274 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2275 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002276 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002277 )
2278 {
2279 /* SoftAP mode, so return from here */
2280 EXIT();
2281 return 0;
2282 }
2283
2284 /* Find if any iface is up then
2285 if any iface is up then can't put device to sleep/ power save mode. */
2286 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2287 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2288 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002289 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2290 {
2291 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302292 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002293 enter_standby = FALSE;
2294 break;
2295 }
2296 else
2297 {
2298 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2299 pAdapterNode = pNext;
2300 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002301 }
2302
2303 if (TRUE == enter_standby)
2304 {
2305 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2306 "entering standby", __func__);
2307 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2308 {
2309 /*log and return success*/
2310 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2311 "wlan in power save", __func__);
2312 }
2313 }
2314
2315 EXIT();
2316 return 0;
2317}
2318
2319/**---------------------------------------------------------------------------
2320
2321 \brief hdd_uninit() - HDD uninit function
2322
2323 This is called during the netdev unregister to uninitialize all data
2324associated with the device
2325
2326 \param - dev Pointer to net_device structure
2327
2328 \return - void
2329
2330 --------------------------------------------------------------------------*/
2331static void hdd_uninit (struct net_device *dev)
2332{
2333 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2334
2335 ENTER();
2336
2337 do
2338 {
2339 if (NULL == pAdapter)
2340 {
2341 hddLog(VOS_TRACE_LEVEL_FATAL,
2342 "%s: NULL pAdapter", __func__);
2343 break;
2344 }
2345
2346 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2347 {
2348 hddLog(VOS_TRACE_LEVEL_FATAL,
2349 "%s: Invalid magic", __func__);
2350 break;
2351 }
2352
2353 if (NULL == pAdapter->pHddCtx)
2354 {
2355 hddLog(VOS_TRACE_LEVEL_FATAL,
2356 "%s: NULL pHddCtx", __func__);
2357 break;
2358 }
2359
2360 if (dev != pAdapter->dev)
2361 {
2362 hddLog(VOS_TRACE_LEVEL_FATAL,
2363 "%s: Invalid device reference", __func__);
2364 /* we haven't validated all cases so let this go for now */
2365 }
2366
2367 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2368
2369 /* after uninit our adapter structure will no longer be valid */
2370 pAdapter->dev = NULL;
2371 pAdapter->magic = 0;
2372 } while (0);
2373
2374 EXIT();
2375}
2376
2377/**---------------------------------------------------------------------------
2378
2379 \brief hdd_release_firmware() -
2380
2381 This function calls the release firmware API to free the firmware buffer.
2382
2383 \param - pFileName Pointer to the File Name.
2384 pCtx - Pointer to the adapter .
2385
2386
2387 \return - 0 for success, non zero for failure
2388
2389 --------------------------------------------------------------------------*/
2390
2391VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2392{
2393 VOS_STATUS status = VOS_STATUS_SUCCESS;
2394 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2395 ENTER();
2396
2397
2398 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2399
2400 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2401
2402 if(pHddCtx->fw) {
2403 release_firmware(pHddCtx->fw);
2404 pHddCtx->fw = NULL;
2405 }
2406 else
2407 status = VOS_STATUS_E_FAILURE;
2408 }
2409 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2410 if(pHddCtx->nv) {
2411 release_firmware(pHddCtx->nv);
2412 pHddCtx->nv = NULL;
2413 }
2414 else
2415 status = VOS_STATUS_E_FAILURE;
2416
2417 }
2418
2419 EXIT();
2420 return status;
2421}
2422
2423/**---------------------------------------------------------------------------
2424
2425 \brief hdd_request_firmware() -
2426
2427 This function reads the firmware file using the request firmware
2428 API and returns the the firmware data and the firmware file size.
2429
2430 \param - pfileName - Pointer to the file name.
2431 - pCtx - Pointer to the adapter .
2432 - ppfw_data - Pointer to the pointer of the firmware data.
2433 - pSize - Pointer to the file size.
2434
2435 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2436
2437 --------------------------------------------------------------------------*/
2438
2439
2440VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2441{
2442 int status;
2443 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2444 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2445 ENTER();
2446
2447 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2448
2449 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2450
2451 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2452 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2453 __func__, pfileName);
2454 retval = VOS_STATUS_E_FAILURE;
2455 }
2456
2457 else {
2458 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2459 *pSize = pHddCtx->fw->size;
2460 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2461 __func__, *pSize);
2462 }
2463 }
2464 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2465
2466 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2467
2468 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2469 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2470 __func__, pfileName);
2471 retval = VOS_STATUS_E_FAILURE;
2472 }
2473
2474 else {
2475 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2476 *pSize = pHddCtx->nv->size;
2477 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2478 __func__, *pSize);
2479 }
2480 }
2481
2482 EXIT();
2483 return retval;
2484}
2485/**---------------------------------------------------------------------------
2486 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2487
2488 This is the function invoked by SME to inform the result of a full power
2489 request issued by HDD
2490
2491 \param - callbackcontext - Pointer to cookie
2492 status - result of request
2493
2494 \return - None
2495
2496--------------------------------------------------------------------------*/
2497void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2498{
2499 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2500
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002501 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002502 if(&pHddCtx->full_pwr_comp_var)
2503 {
2504 complete(&pHddCtx->full_pwr_comp_var);
2505 }
2506}
2507
2508/**---------------------------------------------------------------------------
2509
2510 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2511
2512 This is the function invoked by SME to inform the result of BMPS
2513 request issued by HDD
2514
2515 \param - callbackcontext - Pointer to cookie
2516 status - result of request
2517
2518 \return - None
2519
2520--------------------------------------------------------------------------*/
2521void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2522{
2523
2524 struct completion *completion_var = (struct completion*) callbackContext;
2525
2526 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2527 if(completion_var != NULL)
2528 {
2529 complete(completion_var);
2530 }
2531}
2532
2533/**---------------------------------------------------------------------------
2534
2535 \brief hdd_get_cfg_file_size() -
2536
2537 This function reads the configuration file using the request firmware
2538 API and returns the configuration file size.
2539
2540 \param - pCtx - Pointer to the adapter .
2541 - pFileName - Pointer to the file name.
2542 - pBufSize - Pointer to the buffer size.
2543
2544 \return - 0 for success, non zero for failure
2545
2546 --------------------------------------------------------------------------*/
2547
2548VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2549{
2550 int status;
2551 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2552
2553 ENTER();
2554
2555 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2556
2557 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2558 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2559 status = VOS_STATUS_E_FAILURE;
2560 }
2561 else {
2562 *pBufSize = pHddCtx->fw->size;
2563 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2564 release_firmware(pHddCtx->fw);
2565 pHddCtx->fw = NULL;
2566 }
2567
2568 EXIT();
2569 return VOS_STATUS_SUCCESS;
2570}
2571
2572/**---------------------------------------------------------------------------
2573
2574 \brief hdd_read_cfg_file() -
2575
2576 This function reads the configuration file using the request firmware
2577 API and returns the cfg data and the buffer size of the configuration file.
2578
2579 \param - pCtx - Pointer to the adapter .
2580 - pFileName - Pointer to the file name.
2581 - pBuffer - Pointer to the data buffer.
2582 - pBufSize - Pointer to the buffer size.
2583
2584 \return - 0 for success, non zero for failure
2585
2586 --------------------------------------------------------------------------*/
2587
2588VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2589 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2590{
2591 int status;
2592 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2593
2594 ENTER();
2595
2596 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2597
2598 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2599 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2600 return VOS_STATUS_E_FAILURE;
2601 }
2602 else {
2603 if(*pBufSize != pHddCtx->fw->size) {
2604 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2605 "file size", __func__);
2606 release_firmware(pHddCtx->fw);
2607 pHddCtx->fw = NULL;
2608 return VOS_STATUS_E_FAILURE;
2609 }
2610 else {
2611 if(pBuffer) {
2612 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2613 }
2614 release_firmware(pHddCtx->fw);
2615 pHddCtx->fw = NULL;
2616 }
2617 }
2618
2619 EXIT();
2620
2621 return VOS_STATUS_SUCCESS;
2622}
2623
2624/**---------------------------------------------------------------------------
2625
Jeff Johnson295189b2012-06-20 16:38:30 -07002626 \brief hdd_set_mac_address() -
2627
2628 This function sets the user specified mac address using
2629 the command ifconfig wlanX hw ether <mac adress>.
2630
2631 \param - dev - Pointer to the net device.
2632 - addr - Pointer to the sockaddr.
2633 \return - 0 for success, non zero for failure
2634
2635 --------------------------------------------------------------------------*/
2636
2637static int hdd_set_mac_address(struct net_device *dev, void *addr)
2638{
2639 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2640 struct sockaddr *psta_mac_addr = addr;
2641 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2642
2643 ENTER();
2644
2645 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2646
2647#ifdef HDD_SESSIONIZE
2648 // set the MAC address though the STA ID CFG.
2649 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2650 (v_U8_t *)&pAdapter->macAddressCurrent,
2651 sizeof( pAdapter->macAddressCurrent ),
2652 hdd_set_mac_addr_cb, VOS_FALSE );
2653#endif
2654
2655 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2656
2657 EXIT();
2658 return halStatus;
2659}
2660
2661tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2662{
2663 int i;
2664 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2665 {
2666 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2667 break;
2668 }
2669
2670 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2671 return NULL;
2672
2673 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2674 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2675}
2676
2677void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
2678{
2679 int i;
2680 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2681 {
2682 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
2683 {
2684 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
2685 break;
2686 }
2687 }
2688 return;
2689}
2690
2691#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2692 static struct net_device_ops wlan_drv_ops = {
2693 .ndo_open = hdd_open,
2694 .ndo_stop = hdd_stop,
2695 .ndo_uninit = hdd_uninit,
2696 .ndo_start_xmit = hdd_hard_start_xmit,
2697 .ndo_tx_timeout = hdd_tx_timeout,
2698 .ndo_get_stats = hdd_stats,
2699 .ndo_do_ioctl = hdd_ioctl,
2700 .ndo_set_mac_address = hdd_set_mac_address,
2701 .ndo_select_queue = hdd_select_queue,
2702#ifdef WLAN_FEATURE_PACKET_FILTERING
2703#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
2704 .ndo_set_rx_mode = hdd_set_multicast_list,
2705#else
2706 .ndo_set_multicast_list = hdd_set_multicast_list,
2707#endif //LINUX_VERSION_CODE
2708#endif
2709 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002710 static struct net_device_ops wlan_mon_drv_ops = {
2711 .ndo_open = hdd_mon_open,
2712 .ndo_stop = hdd_stop,
2713 .ndo_uninit = hdd_uninit,
2714 .ndo_start_xmit = hdd_mon_hard_start_xmit,
2715 .ndo_tx_timeout = hdd_tx_timeout,
2716 .ndo_get_stats = hdd_stats,
2717 .ndo_do_ioctl = hdd_ioctl,
2718 .ndo_set_mac_address = hdd_set_mac_address,
2719 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002720
2721#endif
2722
2723void hdd_set_station_ops( struct net_device *pWlanDev )
2724{
2725#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2726 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
2727 pWlanDev->netdev_ops = &wlan_drv_ops;
2728#else
2729 pWlanDev->open = hdd_open;
2730 pWlanDev->stop = hdd_stop;
2731 pWlanDev->uninit = hdd_uninit;
2732 pWlanDev->hard_start_xmit = NULL;
2733 pWlanDev->tx_timeout = hdd_tx_timeout;
2734 pWlanDev->get_stats = hdd_stats;
2735 pWlanDev->do_ioctl = hdd_ioctl;
2736 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
2737 pWlanDev->set_mac_address = hdd_set_mac_address;
2738#endif
2739}
2740
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002741static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07002742{
2743 struct net_device *pWlanDev = NULL;
2744 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002745 /*
2746 * cfg80211 initialization and registration....
2747 */
2748 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
2749
Jeff Johnson295189b2012-06-20 16:38:30 -07002750 if(pWlanDev != NULL)
2751 {
2752
2753 //Save the pointer to the net_device in the HDD adapter
2754 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
2755
Jeff Johnson295189b2012-06-20 16:38:30 -07002756 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
2757
2758 pAdapter->dev = pWlanDev;
2759 pAdapter->pHddCtx = pHddCtx;
2760 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
2761
2762 init_completion(&pAdapter->session_open_comp_var);
2763 init_completion(&pAdapter->session_close_comp_var);
2764 init_completion(&pAdapter->disconnect_comp_var);
2765 init_completion(&pAdapter->linkup_event_var);
2766 init_completion(&pAdapter->cancel_rem_on_chan_var);
2767 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07002768#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2769 init_completion(&pAdapter->offchannel_tx_event);
2770#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002771 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002772#ifdef FEATURE_WLAN_TDLS
2773 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002774 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002775 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002776#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002777 init_completion(&pHddCtx->mc_sus_event_var);
2778 init_completion(&pHddCtx->tx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07002779 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07002780
Jeff Johnson295189b2012-06-20 16:38:30 -07002781 pAdapter->isLinkUpSvcNeeded = FALSE;
2782 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
2783 //Init the net_device structure
2784 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2785
2786 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
2787 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
2788 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
2789 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
2790
2791 hdd_set_station_ops( pAdapter->dev );
2792
2793 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002794 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
2795 pAdapter->wdev.wiphy = pHddCtx->wiphy;
2796 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002797 /* set pWlanDev's parent to underlying device */
2798 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
2799 }
2800
2801 return pAdapter;
2802}
2803
2804VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
2805{
2806 struct net_device *pWlanDev = pAdapter->dev;
2807 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2808 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2809 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2810
2811 if( rtnl_lock_held )
2812 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08002813 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07002814 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
2815 {
2816 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
2817 return VOS_STATUS_E_FAILURE;
2818 }
2819 }
2820 if (register_netdevice(pWlanDev))
2821 {
2822 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
2823 return VOS_STATUS_E_FAILURE;
2824 }
2825 }
2826 else
2827 {
2828 if(register_netdev(pWlanDev))
2829 {
2830 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
2831 return VOS_STATUS_E_FAILURE;
2832 }
2833 }
2834 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
2835
2836 return VOS_STATUS_SUCCESS;
2837}
2838
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002839static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07002840{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002841 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07002842
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002843 if (NULL == pAdapter)
2844 {
2845 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
2846 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07002847 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002848
2849 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2850 {
2851 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
2852 return eHAL_STATUS_NOT_INITIALIZED;
2853 }
2854
2855 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
2856
2857 /* need to make sure all of our scheduled work has completed.
2858 * This callback is called from MC thread context, so it is safe to
2859 * to call below flush workqueue API from here.
2860 */
2861 flush_scheduled_work();
2862
2863 /* We can be blocked while waiting for scheduled work to be
2864 * flushed, and the adapter structure can potentially be freed, in
2865 * which case the magic will have been reset. So make sure the
2866 * magic is still good, and hence the adapter structure is still
2867 * valid, before signaling completion */
2868 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
2869 {
2870 complete(&pAdapter->session_close_comp_var);
2871 }
2872
Jeff Johnson295189b2012-06-20 16:38:30 -07002873 return eHAL_STATUS_SUCCESS;
2874}
2875
2876VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
2877{
2878 struct net_device *pWlanDev = pAdapter->dev;
2879 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2880 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2881 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2882 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2883 int rc = 0;
2884
2885 INIT_COMPLETION(pAdapter->session_open_comp_var);
2886 //Open a SME session for future operation
2887 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
2888 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
2889 if ( !HAL_STATUS_SUCCESS( halStatus ) )
2890 {
2891 hddLog(VOS_TRACE_LEVEL_FATAL,
2892 "sme_OpenSession() failed with status code %08d [x%08lx]",
2893 halStatus, halStatus );
2894 status = VOS_STATUS_E_FAILURE;
2895 goto error_sme_open;
2896 }
2897
2898 //Block on a completion variable. Can't wait forever though.
2899 rc = wait_for_completion_interruptible_timeout(
2900 &pAdapter->session_open_comp_var,
2901 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2902 if (!rc)
2903 {
2904 hddLog(VOS_TRACE_LEVEL_FATAL,
2905 "Session is not opened within timeout period code %08d", rc );
2906 status = VOS_STATUS_E_FAILURE;
2907 goto error_sme_open;
2908 }
2909
2910 // Register wireless extensions
2911 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
2912 {
2913 hddLog(VOS_TRACE_LEVEL_FATAL,
2914 "hdd_register_wext() failed with status code %08d [x%08lx]",
2915 halStatus, halStatus );
2916 status = VOS_STATUS_E_FAILURE;
2917 goto error_register_wext;
2918 }
2919 //Safe to register the hard_start_xmit function again
2920#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2921 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
2922#else
2923 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
2924#endif
2925
2926 //Set the Connection State to Not Connected
2927 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2928
2929 //Set the default operation channel
2930 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
2931
2932 /* Make the default Auth Type as OPEN*/
2933 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2934
2935 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
2936 {
2937 hddLog(VOS_TRACE_LEVEL_FATAL,
2938 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
2939 status, status );
2940 goto error_init_txrx;
2941 }
2942
2943 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2944
2945 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
2946 {
2947 hddLog(VOS_TRACE_LEVEL_FATAL,
2948 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
2949 status, status );
2950 goto error_wmm_init;
2951 }
2952
2953 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2954
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002955#ifdef FEATURE_WLAN_TDLS
2956 if(0 != wlan_hdd_tdls_init(pAdapter))
2957 {
2958 status = VOS_STATUS_E_FAILURE;
2959 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
2960 goto error_tdls_init;
2961 }
2962 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2963#endif
2964
Jeff Johnson295189b2012-06-20 16:38:30 -07002965 return VOS_STATUS_SUCCESS;
2966
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002967#ifdef FEATURE_WLAN_TDLS
2968error_tdls_init:
2969 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2970 hdd_wmm_adapter_close(pAdapter);
2971#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002972error_wmm_init:
2973 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2974 hdd_deinit_tx_rx(pAdapter);
2975error_init_txrx:
2976 hdd_UnregisterWext(pWlanDev);
2977error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002978 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07002979 {
2980 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002981 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002982 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002983 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07002984 {
2985 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002986 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07002987 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002988 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07002989 }
2990}
2991error_sme_open:
2992 return status;
2993}
2994
Jeff Johnson295189b2012-06-20 16:38:30 -07002995void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2996{
2997 hdd_cfg80211_state_t *cfgState;
2998
2999 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3000
3001 if( NULL != cfgState->buf )
3002 {
3003 int rc;
3004 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3005 rc = wait_for_completion_interruptible_timeout(
3006 &pAdapter->tx_action_cnf_event,
3007 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3008 if(!rc)
3009 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003010 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003011 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3012 }
3013 }
3014 return;
3015}
Jeff Johnson295189b2012-06-20 16:38:30 -07003016
3017void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3018{
3019 ENTER();
3020 switch ( pAdapter->device_mode )
3021 {
3022 case WLAN_HDD_INFRA_STATION:
3023 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003024 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003025 {
3026 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3027 {
3028 hdd_deinit_tx_rx( pAdapter );
3029 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3030 }
3031
3032 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3033 {
3034 hdd_wmm_adapter_close( pAdapter );
3035 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3036 }
3037
Jeff Johnson295189b2012-06-20 16:38:30 -07003038 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003039#ifdef FEATURE_WLAN_TDLS
3040 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3041 {
3042 wlan_hdd_tdls_exit(pAdapter);
3043 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3044 }
3045#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003046
3047 break;
3048 }
3049
3050 case WLAN_HDD_SOFTAP:
3051 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003052 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003053 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003054
3055 hdd_unregister_hostapd(pAdapter);
3056 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003057 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003058 break;
3059 }
3060
3061 case WLAN_HDD_MONITOR:
3062 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003063 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003064 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3065 {
3066 hdd_deinit_tx_rx( pAdapter );
3067 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3068 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003069 if(NULL != pAdapterforTx)
3070 {
3071 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3072 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003073 break;
3074 }
3075
3076
3077 default:
3078 break;
3079 }
3080
3081 EXIT();
3082}
3083
3084void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3085{
3086 struct net_device *pWlanDev = pAdapter->dev;
3087
3088 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3089 if( rtnl_held )
3090 {
3091 unregister_netdevice(pWlanDev);
3092 }
3093 else
3094 {
3095 unregister_netdev(pWlanDev);
3096 }
3097 // note that the pAdapter is no longer valid at this point
3098 // since the memory has been reclaimed
3099 }
3100
3101}
3102
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003103void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3104{
3105 tSirSetPowerParamsReq powerRequest = { 0 };
3106
3107 powerRequest.uIgnoreDTIM = 1;
Yue Mac24062f2013-05-13 17:01:29 -07003108 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003109
3110 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3111 {
3112 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3113 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3114 }
3115 else
3116 {
3117 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3118 }
3119
3120 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3121 *specified during Enter/Exit BMPS when LCD off*/
3122 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3123 NULL, eANI_BOOLEAN_FALSE);
3124 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3125 NULL, eANI_BOOLEAN_FALSE);
3126
3127 /* switch to the DTIM specified in cfg.ini */
3128 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3129 "Switch to DTIM%d", powerRequest.uListenInterval);
3130 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3131
3132}
3133
3134void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3135{
3136 /*Switch back to DTIM 1*/
3137 tSirSetPowerParamsReq powerRequest = { 0 };
3138
3139 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3140 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003141 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003142
3143 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3144 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3145 NULL, eANI_BOOLEAN_FALSE);
3146 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3147 NULL, eANI_BOOLEAN_FALSE);
3148
3149 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3150 "Switch to DTIM%d",powerRequest.uListenInterval);
3151 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3152
3153}
3154
Jeff Johnson295189b2012-06-20 16:38:30 -07003155VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3156{
3157 VOS_STATUS status = VOS_STATUS_SUCCESS;
3158
3159 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3160 {
3161 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3162 }
3163
3164 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3165 {
3166 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3167 }
3168
3169 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3170 {
3171 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3172 }
3173
3174 return status;
3175}
3176
3177VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3178{
3179 hdd_adapter_t *pAdapter = NULL;
3180 eHalStatus halStatus;
3181 VOS_STATUS status = VOS_STATUS_E_INVAL;
3182 v_BOOL_t disableBmps = FALSE;
3183 v_BOOL_t disableImps = FALSE;
3184
3185 switch(session_type)
3186 {
3187 case WLAN_HDD_INFRA_STATION:
3188 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003189 case WLAN_HDD_P2P_CLIENT:
3190 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003191 //Exit BMPS -> Is Sta/P2P Client is already connected
3192 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3193 if((NULL != pAdapter)&&
3194 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3195 {
3196 disableBmps = TRUE;
3197 }
3198
3199 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3200 if((NULL != pAdapter)&&
3201 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3202 {
3203 disableBmps = TRUE;
3204 }
3205
3206 //Exit both Bmps and Imps incase of Go/SAP Mode
3207 if((WLAN_HDD_SOFTAP == session_type) ||
3208 (WLAN_HDD_P2P_GO == session_type))
3209 {
3210 disableBmps = TRUE;
3211 disableImps = TRUE;
3212 }
3213
3214 if(TRUE == disableImps)
3215 {
3216 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3217 {
3218 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3219 }
3220 }
3221
3222 if(TRUE == disableBmps)
3223 {
3224 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3225 {
3226 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3227
3228 if(eHAL_STATUS_SUCCESS != halStatus)
3229 {
3230 status = VOS_STATUS_E_FAILURE;
3231 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3232 VOS_ASSERT(0);
3233 return status;
3234 }
3235 }
3236
3237 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3238 {
3239 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3240
3241 if(eHAL_STATUS_SUCCESS != halStatus)
3242 {
3243 status = VOS_STATUS_E_FAILURE;
3244 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3245 VOS_ASSERT(0);
3246 return status;
3247 }
3248 }
3249 }
3250
3251 if((TRUE == disableBmps) ||
3252 (TRUE == disableImps))
3253 {
3254 /* Now, get the chip into Full Power now */
3255 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3256 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3257 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3258
3259 if(halStatus != eHAL_STATUS_SUCCESS)
3260 {
3261 if(halStatus == eHAL_STATUS_PMC_PENDING)
3262 {
3263 //Block on a completion variable. Can't wait forever though
3264 wait_for_completion_interruptible_timeout(
3265 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3266 }
3267 else
3268 {
3269 status = VOS_STATUS_E_FAILURE;
3270 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3271 VOS_ASSERT(0);
3272 return status;
3273 }
3274 }
3275
3276 status = VOS_STATUS_SUCCESS;
3277 }
3278
3279 break;
3280 }
3281 return status;
3282}
3283
3284hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003285 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003286 tANI_U8 rtnl_held )
3287{
3288 hdd_adapter_t *pAdapter = NULL;
3289 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3290 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3291 VOS_STATUS exitbmpsStatus;
3292
3293 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3294
3295 //Disable BMPS incase of Concurrency
3296 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3297
3298 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3299 {
3300 //Fail to Exit BMPS
3301 VOS_ASSERT(0);
3302 return NULL;
3303 }
3304
3305 switch(session_type)
3306 {
3307 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003308 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003309 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003310 {
3311 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3312
3313 if( NULL == pAdapter )
3314 return NULL;
3315
Jeff Johnsone7245742012-09-05 17:12:55 -07003316 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3317 NL80211_IFTYPE_P2P_CLIENT:
3318 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003319
Jeff Johnson295189b2012-06-20 16:38:30 -07003320 pAdapter->device_mode = session_type;
3321
3322 status = hdd_init_station_mode( pAdapter );
3323 if( VOS_STATUS_SUCCESS != status )
3324 goto err_free_netdev;
3325
3326 status = hdd_register_interface( pAdapter, rtnl_held );
3327 if( VOS_STATUS_SUCCESS != status )
3328 {
3329 hdd_deinit_adapter(pHddCtx, pAdapter);
3330 goto err_free_netdev;
3331 }
3332 //Stop the Interface TX queue.
3333 netif_tx_disable(pAdapter->dev);
3334 //netif_tx_disable(pWlanDev);
3335 netif_carrier_off(pAdapter->dev);
3336
3337 break;
3338 }
3339
Jeff Johnson295189b2012-06-20 16:38:30 -07003340 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003341 case WLAN_HDD_SOFTAP:
3342 {
3343 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3344 if( NULL == pAdapter )
3345 return NULL;
3346
Jeff Johnson295189b2012-06-20 16:38:30 -07003347 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3348 NL80211_IFTYPE_AP:
3349 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003350 pAdapter->device_mode = session_type;
3351
3352 status = hdd_init_ap_mode(pAdapter);
3353 if( VOS_STATUS_SUCCESS != status )
3354 goto err_free_netdev;
3355
3356 status = hdd_register_hostapd( pAdapter, rtnl_held );
3357 if( VOS_STATUS_SUCCESS != status )
3358 {
3359 hdd_deinit_adapter(pHddCtx, pAdapter);
3360 goto err_free_netdev;
3361 }
3362
3363 netif_tx_disable(pAdapter->dev);
3364 netif_carrier_off(pAdapter->dev);
3365
3366 hdd_set_conparam( 1 );
3367 break;
3368 }
3369 case WLAN_HDD_MONITOR:
3370 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003371 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3372 if( NULL == pAdapter )
3373 return NULL;
3374
3375 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3376 pAdapter->device_mode = session_type;
3377 status = hdd_register_interface( pAdapter, rtnl_held );
3378#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3379 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3380#else
3381 pAdapter->dev->open = hdd_mon_open;
3382 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3383#endif
3384 hdd_init_tx_rx( pAdapter );
3385 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3386 //Set adapter to be used for data tx. It will use either GO or softap.
3387 pAdapter->sessionCtx.monitor.pAdapterForTx =
3388 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003389 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3390 {
3391 pAdapter->sessionCtx.monitor.pAdapterForTx =
3392 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3393 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003394 /* This workqueue will be used to transmit management packet over
3395 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003396 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3397 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3398 return NULL;
3399 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003400
Jeff Johnson295189b2012-06-20 16:38:30 -07003401 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3402 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003403 }
3404 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003405 case WLAN_HDD_FTM:
3406 {
3407 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3408
3409 if( NULL == pAdapter )
3410 return NULL;
3411 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3412 * message while loading driver in FTM mode. */
3413 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3414 pAdapter->device_mode = session_type;
3415 status = hdd_register_interface( pAdapter, rtnl_held );
3416 }
3417 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003418 default:
3419 {
3420 VOS_ASSERT(0);
3421 return NULL;
3422 }
3423 }
3424
3425
3426 if( VOS_STATUS_SUCCESS == status )
3427 {
3428 //Add it to the hdd's session list.
3429 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3430 if( NULL == pHddAdapterNode )
3431 {
3432 status = VOS_STATUS_E_NOMEM;
3433 }
3434 else
3435 {
3436 pHddAdapterNode->pAdapter = pAdapter;
3437 status = hdd_add_adapter_back ( pHddCtx,
3438 pHddAdapterNode );
3439 }
3440 }
3441
3442 if( VOS_STATUS_SUCCESS != status )
3443 {
3444 if( NULL != pAdapter )
3445 {
3446 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3447 pAdapter = NULL;
3448 }
3449 if( NULL != pHddAdapterNode )
3450 {
3451 vos_mem_free( pHddAdapterNode );
3452 }
3453
3454 goto resume_bmps;
3455 }
3456
3457 if(VOS_STATUS_SUCCESS == status)
3458 {
3459 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3460
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003461 //Initialize the WoWL service
3462 if(!hdd_init_wowl(pAdapter))
3463 {
3464 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3465 goto err_free_netdev;
3466 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003467 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003468 return pAdapter;
3469
3470err_free_netdev:
3471 free_netdev(pAdapter->dev);
3472 wlan_hdd_release_intf_addr( pHddCtx,
3473 pAdapter->macAddressCurrent.bytes );
3474
3475resume_bmps:
3476 //If bmps disabled enable it
3477 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3478 {
3479 hdd_enable_bmps_imps(pHddCtx);
3480 }
3481 return NULL;
3482}
3483
3484VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3485 tANI_U8 rtnl_held )
3486{
3487 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3488 VOS_STATUS status;
3489
3490 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3491 if( VOS_STATUS_SUCCESS != status )
3492 return status;
3493
3494 while ( pCurrent->pAdapter != pAdapter )
3495 {
3496 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3497 if( VOS_STATUS_SUCCESS != status )
3498 break;
3499
3500 pCurrent = pNext;
3501 }
3502 pAdapterNode = pCurrent;
3503 if( VOS_STATUS_SUCCESS == status )
3504 {
3505 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3506 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3507 hdd_remove_adapter( pHddCtx, pAdapterNode );
3508 vos_mem_free( pAdapterNode );
3509
Jeff Johnson295189b2012-06-20 16:38:30 -07003510
3511 /* If there is a single session of STA/P2P client, re-enable BMPS */
3512 if ((!vos_concurrent_sessions_running()) &&
3513 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3514 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3515 {
3516 hdd_enable_bmps_imps(pHddCtx);
3517 }
3518
3519 return VOS_STATUS_SUCCESS;
3520 }
3521
3522 return VOS_STATUS_E_FAILURE;
3523}
3524
3525VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3526{
3527 hdd_adapter_list_node_t *pHddAdapterNode;
3528 VOS_STATUS status;
3529
3530 ENTER();
3531
3532 do
3533 {
3534 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3535 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3536 {
3537 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3538 vos_mem_free( pHddAdapterNode );
3539 }
3540 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3541
3542 EXIT();
3543
3544 return VOS_STATUS_SUCCESS;
3545}
3546
3547void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3548{
3549 v_U8_t addIE[1] = {0};
3550
3551 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3552 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3553 eANI_BOOLEAN_FALSE) )
3554 {
3555 hddLog(LOGE,
3556 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3557 }
3558
3559 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3560 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3561 eANI_BOOLEAN_FALSE) )
3562 {
3563 hddLog(LOGE,
3564 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3565 }
3566
3567 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3568 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3569 eANI_BOOLEAN_FALSE) )
3570 {
3571 hddLog(LOGE,
3572 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3573 }
3574}
3575
3576VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3577{
3578 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3579 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3580 union iwreq_data wrqu;
3581
3582 ENTER();
3583
3584 switch(pAdapter->device_mode)
3585 {
3586 case WLAN_HDD_INFRA_STATION:
3587 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003588 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003589 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3590 {
3591 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3592 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3593 pAdapter->sessionId,
3594 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3595 else
3596 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3597 pAdapter->sessionId,
3598 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3599 //success implies disconnect command got queued up successfully
3600 if(halStatus == eHAL_STATUS_SUCCESS)
3601 {
3602 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3603 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3604 }
3605 memset(&wrqu, '\0', sizeof(wrqu));
3606 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3607 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3608 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3609 }
3610 else
3611 {
3612 hdd_abort_mac_scan(pHddCtx);
3613 }
3614
3615 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3616 {
3617 INIT_COMPLETION(pAdapter->session_close_comp_var);
3618 if (eHAL_STATUS_SUCCESS ==
3619 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3620 hdd_smeCloseSessionCallback, pAdapter))
3621 {
3622 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003623 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003624 &pAdapter->session_close_comp_var,
3625 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3626 }
3627 }
3628
3629 break;
3630
3631 case WLAN_HDD_SOFTAP:
3632 case WLAN_HDD_P2P_GO:
3633 //Any softap specific cleanup here...
3634 mutex_lock(&pHddCtx->sap_lock);
3635 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3636 {
3637 VOS_STATUS status;
3638 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3639
3640 //Stop Bss.
3641 status = WLANSAP_StopBss(pHddCtx->pvosContext);
3642 if (VOS_IS_STATUS_SUCCESS(status))
3643 {
3644 hdd_hostapd_state_t *pHostapdState =
3645 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3646
3647 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
3648
3649 if (!VOS_IS_STATUS_SUCCESS(status))
3650 {
3651 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003652 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003653 }
3654 }
3655 else
3656 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003657 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003658 }
3659 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
3660
3661 if (eHAL_STATUS_FAILURE ==
3662 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
3663 0, NULL, eANI_BOOLEAN_FALSE))
3664 {
3665 hddLog(LOGE,
3666 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003667 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003668 }
3669
3670 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
3671 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
3672 eANI_BOOLEAN_FALSE) )
3673 {
3674 hddLog(LOGE,
3675 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
3676 }
3677
3678 // Reset WNI_CFG_PROBE_RSP Flags
3679 wlan_hdd_reset_prob_rspies(pAdapter);
3680 kfree(pAdapter->sessionCtx.ap.beacon);
3681 pAdapter->sessionCtx.ap.beacon = NULL;
3682 }
3683 mutex_unlock(&pHddCtx->sap_lock);
3684 break;
3685 case WLAN_HDD_MONITOR:
3686 break;
3687 default:
3688 break;
3689 }
3690
3691 EXIT();
3692 return VOS_STATUS_SUCCESS;
3693}
3694
3695VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
3696{
3697 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3698 VOS_STATUS status;
3699 hdd_adapter_t *pAdapter;
3700
3701 ENTER();
3702
3703 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3704
3705 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3706 {
3707 pAdapter = pAdapterNode->pAdapter;
3708 netif_tx_disable(pAdapter->dev);
3709 netif_carrier_off(pAdapter->dev);
3710
3711 hdd_stop_adapter( pHddCtx, pAdapter );
3712
3713 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3714 pAdapterNode = pNext;
3715 }
3716
3717 EXIT();
3718
3719 return VOS_STATUS_SUCCESS;
3720}
3721
3722VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
3723{
3724 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3725 VOS_STATUS status;
3726 hdd_adapter_t *pAdapter;
3727
3728 ENTER();
3729
3730 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3731
3732 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3733 {
3734 pAdapter = pAdapterNode->pAdapter;
3735 netif_tx_disable(pAdapter->dev);
3736 netif_carrier_off(pAdapter->dev);
3737
3738 //Record whether STA is associated
3739 pAdapter->sessionCtx.station.bSendDisconnect =
3740 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
3741 VOS_TRUE : VOS_FALSE;
3742
3743 hdd_deinit_tx_rx(pAdapter);
3744 hdd_wmm_adapter_close(pAdapter);
3745
3746 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3747 pAdapterNode = pNext;
3748 }
3749
3750 EXIT();
3751
3752 return VOS_STATUS_SUCCESS;
3753}
3754
3755VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
3756{
3757 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3758 VOS_STATUS status;
3759 hdd_adapter_t *pAdapter;
3760 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
3761
3762 ENTER();
3763
3764 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3765
3766 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3767 {
3768 pAdapter = pAdapterNode->pAdapter;
3769
3770 switch(pAdapter->device_mode)
3771 {
3772 case WLAN_HDD_INFRA_STATION:
3773 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003774 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003775 hdd_init_station_mode(pAdapter);
3776 /* Open the gates for HDD to receive Wext commands */
3777 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003778 pHddCtx->scan_info.mScanPending = FALSE;
3779 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003780
3781 //Trigger the initial scan
3782 hdd_wlan_initial_scan(pAdapter);
3783
3784 //Indicate disconnect event to supplicant if associated previously
3785 if(pAdapter->sessionCtx.station.bSendDisconnect)
3786 {
3787 union iwreq_data wrqu;
3788 memset(&wrqu, '\0', sizeof(wrqu));
3789 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3790 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3791 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3792 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
3793
Jeff Johnson295189b2012-06-20 16:38:30 -07003794 /* indicate disconnected event to nl80211 */
3795 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
3796 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003797 }
3798 break;
3799
3800 case WLAN_HDD_SOFTAP:
3801 /* softAP can handle SSR */
3802 break;
3803
3804 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003805 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
3806 __func__);
3807 /* event supplicant to restart */
3808 cfg80211_del_sta(pAdapter->dev,
3809 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003810 break;
3811
3812 case WLAN_HDD_MONITOR:
3813 /* monitor interface start */
3814 break;
3815 default:
3816 break;
3817 }
3818
3819 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3820 pAdapterNode = pNext;
3821 }
3822
3823 EXIT();
3824
3825 return VOS_STATUS_SUCCESS;
3826}
3827
3828VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
3829{
3830 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3831 hdd_adapter_t *pAdapter;
3832 VOS_STATUS status;
3833 v_U32_t roamId;
3834
3835 ENTER();
3836
3837 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3838
3839 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3840 {
3841 pAdapter = pAdapterNode->pAdapter;
3842
3843 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3844 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
3845 {
3846 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3847 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3848
3849 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3850 init_completion(&pAdapter->disconnect_comp_var);
3851 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
3852 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3853
3854 wait_for_completion_interruptible_timeout(
3855 &pAdapter->disconnect_comp_var,
3856 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3857
3858 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
3859 pHddCtx->isAmpAllowed = VOS_FALSE;
3860 sme_RoamConnect(pHddCtx->hHal,
3861 pAdapter->sessionId, &(pWextState->roamProfile),
3862 &roamId);
3863 }
3864
3865 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3866 pAdapterNode = pNext;
3867 }
3868
3869 EXIT();
3870
3871 return VOS_STATUS_SUCCESS;
3872}
3873
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07003874void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
3875{
3876 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3877 VOS_STATUS status;
3878 hdd_adapter_t *pAdapter;
3879 hdd_station_ctx_t *pHddStaCtx;
3880 hdd_ap_ctx_t *pHddApCtx;
3881 hdd_hostapd_state_t * pHostapdState;
3882 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
3883 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
3884 const char *p2pMode = "DEV";
3885 const char *ccMode = "Standalone";
3886 int n;
3887
3888 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3889 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3890 {
3891 pAdapter = pAdapterNode->pAdapter;
3892 switch (pAdapter->device_mode) {
3893 case WLAN_HDD_INFRA_STATION:
3894 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3895 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3896 staChannel = pHddStaCtx->conn_info.operationChannel;
3897 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
3898 }
3899 break;
3900 case WLAN_HDD_P2P_CLIENT:
3901 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3902 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3903 p2pChannel = pHddStaCtx->conn_info.operationChannel;
3904 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
3905 p2pMode = "CLI";
3906 }
3907 break;
3908 case WLAN_HDD_P2P_GO:
3909 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3910 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3911 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3912 p2pChannel = pHddApCtx->operatingChannel;
3913 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
3914 }
3915 p2pMode = "GO";
3916 break;
3917 case WLAN_HDD_SOFTAP:
3918 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3919 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3920 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3921 apChannel = pHddApCtx->operatingChannel;
3922 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
3923 }
3924 break;
3925 default:
3926 break;
3927 }
3928 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3929 pAdapterNode = pNext;
3930 }
3931 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
3932 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
3933 }
3934 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
3935 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
3936 if (p2pChannel > 0) {
3937 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
3938 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
3939 }
3940 if (apChannel > 0) {
3941 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
3942 apChannel, MAC_ADDR_ARRAY(apBssid));
3943 }
3944
3945 if (p2pChannel > 0 && apChannel > 0) {
3946 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
3947 }
3948}
3949
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003950bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07003951{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003952 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07003953}
3954
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003955/* Once SSR is disabled then it cannot be set. */
3956void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07003957{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003958 if (HDD_SSR_DISABLED == isSsrRequired)
3959 return;
3960
Jeff Johnson295189b2012-06-20 16:38:30 -07003961 isSsrRequired = value;
3962}
3963
3964VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
3965 hdd_adapter_list_node_t** ppAdapterNode)
3966{
3967 VOS_STATUS status;
3968 spin_lock(&pHddCtx->hddAdapters.lock);
3969 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
3970 (hdd_list_node_t**) ppAdapterNode );
3971 spin_unlock(&pHddCtx->hddAdapters.lock);
3972 return status;
3973}
3974
3975VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
3976 hdd_adapter_list_node_t* pAdapterNode,
3977 hdd_adapter_list_node_t** pNextAdapterNode)
3978{
3979 VOS_STATUS status;
3980 spin_lock(&pHddCtx->hddAdapters.lock);
3981 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
3982 (hdd_list_node_t*) pAdapterNode,
3983 (hdd_list_node_t**)pNextAdapterNode );
3984
3985 spin_unlock(&pHddCtx->hddAdapters.lock);
3986 return status;
3987}
3988
3989VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
3990 hdd_adapter_list_node_t* pAdapterNode)
3991{
3992 VOS_STATUS status;
3993 spin_lock(&pHddCtx->hddAdapters.lock);
3994 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
3995 &pAdapterNode->node );
3996 spin_unlock(&pHddCtx->hddAdapters.lock);
3997 return status;
3998}
3999
4000VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4001 hdd_adapter_list_node_t** ppAdapterNode)
4002{
4003 VOS_STATUS status;
4004 spin_lock(&pHddCtx->hddAdapters.lock);
4005 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4006 (hdd_list_node_t**) ppAdapterNode );
4007 spin_unlock(&pHddCtx->hddAdapters.lock);
4008 return status;
4009}
4010
4011VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4012 hdd_adapter_list_node_t* pAdapterNode)
4013{
4014 VOS_STATUS status;
4015 spin_lock(&pHddCtx->hddAdapters.lock);
4016 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4017 (hdd_list_node_t*) pAdapterNode );
4018 spin_unlock(&pHddCtx->hddAdapters.lock);
4019 return status;
4020}
4021
4022VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4023 hdd_adapter_list_node_t* pAdapterNode)
4024{
4025 VOS_STATUS status;
4026 spin_lock(&pHddCtx->hddAdapters.lock);
4027 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4028 (hdd_list_node_t*) pAdapterNode );
4029 spin_unlock(&pHddCtx->hddAdapters.lock);
4030 return status;
4031}
4032
4033hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4034 tSirMacAddr macAddr )
4035{
4036 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4037 hdd_adapter_t *pAdapter;
4038 VOS_STATUS status;
4039
4040 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4041
4042 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4043 {
4044 pAdapter = pAdapterNode->pAdapter;
4045
4046 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4047 macAddr, sizeof(tSirMacAddr) ) )
4048 {
4049 return pAdapter;
4050 }
4051 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4052 pAdapterNode = pNext;
4053 }
4054
4055 return NULL;
4056
4057}
4058
4059hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4060{
4061 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4062 hdd_adapter_t *pAdapter;
4063 VOS_STATUS status;
4064
4065 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4066
4067 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4068 {
4069 pAdapter = pAdapterNode->pAdapter;
4070
4071 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4072 IFNAMSIZ ) )
4073 {
4074 return pAdapter;
4075 }
4076 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4077 pAdapterNode = pNext;
4078 }
4079
4080 return NULL;
4081
4082}
4083
4084hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4085{
4086 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4087 hdd_adapter_t *pAdapter;
4088 VOS_STATUS status;
4089
4090 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4091
4092 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4093 {
4094 pAdapter = pAdapterNode->pAdapter;
4095
4096 if( pAdapter && (mode == pAdapter->device_mode) )
4097 {
4098 return pAdapter;
4099 }
4100 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4101 pAdapterNode = pNext;
4102 }
4103
4104 return NULL;
4105
4106}
4107
4108//Remove this function later
4109hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4110{
4111 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4112 hdd_adapter_t *pAdapter;
4113 VOS_STATUS status;
4114
4115 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4116
4117 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4118 {
4119 pAdapter = pAdapterNode->pAdapter;
4120
4121 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4122 {
4123 return pAdapter;
4124 }
4125
4126 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4127 pAdapterNode = pNext;
4128 }
4129
4130 return NULL;
4131
4132}
4133
Jeff Johnson295189b2012-06-20 16:38:30 -07004134/**---------------------------------------------------------------------------
4135
4136 \brief hdd_set_monitor_tx_adapter() -
4137
4138 This API initializes the adapter to be used while transmitting on monitor
4139 adapter.
4140
4141 \param - pHddCtx - Pointer to the HDD context.
4142 pAdapter - Adapter that will used for TX. This can be NULL.
4143 \return - None.
4144 --------------------------------------------------------------------------*/
4145void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4146{
4147 hdd_adapter_t *pMonAdapter;
4148
4149 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4150
4151 if( NULL != pMonAdapter )
4152 {
4153 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4154 }
4155}
Jeff Johnson295189b2012-06-20 16:38:30 -07004156/**---------------------------------------------------------------------------
4157
4158 \brief hdd_select_queue() -
4159
4160 This API returns the operating channel of the requested device mode
4161
4162 \param - pHddCtx - Pointer to the HDD context.
4163 - mode - Device mode for which operating channel is required
4164 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4165 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4166 \return - channel number. "0" id the requested device is not found OR it is not connected.
4167 --------------------------------------------------------------------------*/
4168v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4169{
4170 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4171 VOS_STATUS status;
4172 hdd_adapter_t *pAdapter;
4173 v_U8_t operatingChannel = 0;
4174
4175 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4176
4177 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4178 {
4179 pAdapter = pAdapterNode->pAdapter;
4180
4181 if( mode == pAdapter->device_mode )
4182 {
4183 switch(pAdapter->device_mode)
4184 {
4185 case WLAN_HDD_INFRA_STATION:
4186 case WLAN_HDD_P2P_CLIENT:
4187 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4188 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4189 break;
4190 case WLAN_HDD_SOFTAP:
4191 case WLAN_HDD_P2P_GO:
4192 /*softap connection info */
4193 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4194 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4195 break;
4196 default:
4197 break;
4198 }
4199
4200 break; //Found the device of interest. break the loop
4201 }
4202
4203 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4204 pAdapterNode = pNext;
4205 }
4206 return operatingChannel;
4207}
4208
4209#ifdef WLAN_FEATURE_PACKET_FILTERING
4210/**---------------------------------------------------------------------------
4211
4212 \brief hdd_set_multicast_list() -
4213
4214 This used to set the multicast address list.
4215
4216 \param - dev - Pointer to the WLAN device.
4217 - skb - Pointer to OS packet (sk_buff).
4218 \return - success/fail
4219
4220 --------------------------------------------------------------------------*/
4221static void hdd_set_multicast_list(struct net_device *dev)
4222{
4223 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004224 int mc_count;
4225 int i = 0;
4226 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304227
4228 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004229 {
4230 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304231 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004232 return;
4233 }
4234
4235 if (dev->flags & IFF_ALLMULTI)
4236 {
4237 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004238 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304239 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004240 }
4241 else
4242 {
4243 mc_count = netdev_mc_count(dev);
4244 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004245 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004246 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4247 {
4248 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004249 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304250 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004251 return;
4252 }
4253
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304254 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004255
4256 netdev_for_each_mc_addr(ha, dev) {
4257 if (i == mc_count)
4258 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304259 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4260 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4261 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004262 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304263 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004264 i++;
4265 }
4266 }
4267 return;
4268}
4269#endif
4270
4271/**---------------------------------------------------------------------------
4272
4273 \brief hdd_select_queue() -
4274
4275 This function is registered with the Linux OS for network
4276 core to decide which queue to use first.
4277
4278 \param - dev - Pointer to the WLAN device.
4279 - skb - Pointer to OS packet (sk_buff).
4280 \return - ac, Queue Index/access category corresponding to UP in IP header
4281
4282 --------------------------------------------------------------------------*/
4283v_U16_t hdd_select_queue(struct net_device *dev,
4284 struct sk_buff *skb)
4285{
4286 return hdd_wmm_select_queue(dev, skb);
4287}
4288
4289
4290/**---------------------------------------------------------------------------
4291
4292 \brief hdd_wlan_initial_scan() -
4293
4294 This function triggers the initial scan
4295
4296 \param - pAdapter - Pointer to the HDD adapter.
4297
4298 --------------------------------------------------------------------------*/
4299void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4300{
4301 tCsrScanRequest scanReq;
4302 tCsrChannelInfo channelInfo;
4303 eHalStatus halStatus;
4304 unsigned long scanId;
4305 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4306
4307 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4308 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4309 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4310
4311 if(sme_Is11dSupported(pHddCtx->hHal))
4312 {
4313 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4314 if ( HAL_STATUS_SUCCESS( halStatus ) )
4315 {
4316 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4317 if( !scanReq.ChannelInfo.ChannelList )
4318 {
4319 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4320 vos_mem_free(channelInfo.ChannelList);
4321 return;
4322 }
4323 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4324 channelInfo.numOfChannels);
4325 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4326 vos_mem_free(channelInfo.ChannelList);
4327 }
4328
4329 scanReq.scanType = eSIR_PASSIVE_SCAN;
4330 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4331 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4332 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4333 }
4334 else
4335 {
4336 scanReq.scanType = eSIR_ACTIVE_SCAN;
4337 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4338 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4339 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4340 }
4341
4342 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4343 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4344 {
4345 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4346 __func__, halStatus );
4347 }
4348
4349 if(sme_Is11dSupported(pHddCtx->hHal))
4350 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4351}
4352
4353struct fullPowerContext
4354{
4355 struct completion completion;
4356 unsigned int magic;
4357};
4358#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4359
4360/**---------------------------------------------------------------------------
4361
4362 \brief hdd_full_power_callback() - HDD full power callback function
4363
4364 This is the function invoked by SME to inform the result of a full power
4365 request issued by HDD
4366
4367 \param - callbackcontext - Pointer to cookie
4368 \param - status - result of request
4369
4370 \return - None
4371
4372 --------------------------------------------------------------------------*/
4373static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4374{
4375 struct fullPowerContext *pContext = callbackContext;
4376
4377 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304378 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004379
4380 if (NULL == callbackContext)
4381 {
4382 hddLog(VOS_TRACE_LEVEL_ERROR,
4383 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004384 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004385 return;
4386 }
4387
4388 /* there is a race condition that exists between this callback function
4389 and the caller since the caller could time out either before or
4390 while this code is executing. we'll assume the timeout hasn't
4391 occurred, but we'll verify that right before we save our work */
4392
4393 if (POWER_CONTEXT_MAGIC != pContext->magic)
4394 {
4395 /* the caller presumably timed out so there is nothing we can do */
4396 hddLog(VOS_TRACE_LEVEL_WARN,
4397 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004398 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004399 return;
4400 }
4401
4402 /* the race is on. caller could have timed out immediately after
4403 we verified the magic, but if so, caller will wait a short time
4404 for us to notify the caller, so the context will stay valid */
4405 complete(&pContext->completion);
4406}
4407
4408/**---------------------------------------------------------------------------
4409
4410 \brief hdd_wlan_exit() - HDD WLAN exit function
4411
4412 This is the driver exit point (invoked during rmmod)
4413
4414 \param - pHddCtx - Pointer to the HDD Context
4415
4416 \return - None
4417
4418 --------------------------------------------------------------------------*/
4419void hdd_wlan_exit(hdd_context_t *pHddCtx)
4420{
4421 eHalStatus halStatus;
4422 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4423 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304424 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004425 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004426 struct fullPowerContext powerContext;
4427 long lrc;
4428
4429 ENTER();
4430
Jeff Johnson88ba7742013-02-27 14:36:02 -08004431 if (VOS_FTM_MODE != hdd_get_conparam())
4432 {
4433 // Unloading, restart logic is no more required.
4434 wlan_hdd_restart_deinit(pHddCtx);
4435 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004436
Jeff Johnson295189b2012-06-20 16:38:30 -07004437 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004438 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004439 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004440 {
4441 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4442 WLAN_HDD_INFRA_STATION);
4443 if (pAdapter == NULL)
4444 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4445
4446 if (pAdapter != NULL)
4447 {
4448 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4449 hdd_UnregisterWext(pAdapter->dev);
4450 }
4451 }
4452 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004453
Jeff Johnson295189b2012-06-20 16:38:30 -07004454 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004455 {
4456 wlan_hdd_ftm_close(pHddCtx);
4457 goto free_hdd_ctx;
4458 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004459 //Stop the Interface TX queue.
4460 //netif_tx_disable(pWlanDev);
4461 //netif_carrier_off(pWlanDev);
4462
Jeff Johnson295189b2012-06-20 16:38:30 -07004463 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4464 {
4465 pAdapter = hdd_get_adapter(pHddCtx,
4466 WLAN_HDD_SOFTAP);
4467 }
4468 else
4469 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004470 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004471 {
4472 pAdapter = hdd_get_adapter(pHddCtx,
4473 WLAN_HDD_INFRA_STATION);
4474 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004475 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004476 /* DeRegister with platform driver as client for Suspend/Resume */
4477 vosStatus = hddDeregisterPmOps(pHddCtx);
4478 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4479 {
4480 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4481 VOS_ASSERT(0);
4482 }
4483
4484 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4485 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4486 {
4487 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4488 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004489
4490 // Cancel any outstanding scan requests. We are about to close all
4491 // of our adapters, but an adapter structure is what SME passes back
4492 // to our callback function. Hence if there are any outstanding scan
4493 // requests then there is a race condition between when the adapter
4494 // is closed and when the callback is invoked. We try to resolve that
4495 // race condition here by canceling any outstanding scans before we
4496 // close the adapters.
4497 // Note that the scans may be cancelled in an asynchronous manner, so
4498 // ideally there needs to be some kind of synchronization. Rather than
4499 // introduce a new synchronization here, we will utilize the fact that
4500 // we are about to Request Full Power, and since that is synchronized,
4501 // the expectation is that by the time Request Full Power has completed,
4502 // all scans will be cancelled.
4503 hdd_abort_mac_scan( pHddCtx );
4504
4505 //Disable IMPS/BMPS as we do not want the device to enter any power
4506 //save mode during shutdown
4507 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4508 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4509 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4510
4511 //Ensure that device is in full power as we will touch H/W during vos_Stop
4512 init_completion(&powerContext.completion);
4513 powerContext.magic = POWER_CONTEXT_MAGIC;
4514
4515 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4516 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4517
4518 if (eHAL_STATUS_SUCCESS != halStatus)
4519 {
4520 if (eHAL_STATUS_PMC_PENDING == halStatus)
4521 {
4522 /* request was sent -- wait for the response */
4523 lrc = wait_for_completion_interruptible_timeout(
4524 &powerContext.completion,
4525 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4526 /* either we have a response or we timed out
4527 either way, first invalidate our magic */
4528 powerContext.magic = 0;
4529 if (lrc <= 0)
4530 {
4531 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004532 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004533 /* there is a race condition such that the callback
4534 function could be executing at the same time we are. of
4535 primary concern is if the callback function had already
4536 verified the "magic" but hasn't yet set the completion
4537 variable. Since the completion variable is on our
4538 stack, we'll delay just a bit to make sure the data is
4539 still valid if that is the case */
4540 msleep(50);
4541 }
4542 }
4543 else
4544 {
4545 hddLog(VOS_TRACE_LEVEL_ERROR,
4546 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004547 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004548 VOS_ASSERT(0);
4549 /* continue -- need to clean up as much as possible */
4550 }
4551 }
4552
4553 // Unregister the Net Device Notifier
4554 unregister_netdevice_notifier(&hdd_netdev_notifier);
4555
Jeff Johnson295189b2012-06-20 16:38:30 -07004556 hdd_stop_all_adapters( pHddCtx );
4557
Jeff Johnson295189b2012-06-20 16:38:30 -07004558#ifdef WLAN_BTAMP_FEATURE
4559 vosStatus = WLANBAP_Stop(pVosContext);
4560 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4561 {
4562 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4563 "%s: Failed to stop BAP",__func__);
4564 }
4565#endif //WLAN_BTAMP_FEATURE
4566
4567 //Stop all the modules
4568 vosStatus = vos_stop( pVosContext );
4569 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4570 {
4571 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4572 "%s: Failed to stop VOSS",__func__);
4573 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4574 }
4575
Jeff Johnson295189b2012-06-20 16:38:30 -07004576 //Assert Deep sleep signal now to put Libra HW in lowest power state
4577 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4578 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4579
4580 //Vote off any PMIC voltage supplies
4581 vos_chipPowerDown(NULL, NULL, NULL);
4582
4583 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4584
4585 //Clean up HDD Nlink Service
4586 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
4587 nl_srv_exit();
4588
4589 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004590 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004591
4592 //Close the scheduler before calling vos_close to make sure no thread is
4593 // scheduled after the each module close is called i.e after all the data
4594 // structures are freed.
4595 vosStatus = vos_sched_close( pVosContext );
4596 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4597 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4598 "%s: Failed to close VOSS Scheduler",__func__);
4599 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4600 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004601#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004602#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4603 /* Destroy the wake lock */
4604 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4605#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004606 /* Destroy the wake lock */
4607 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004608#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004609
4610 //Close VOSS
4611 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4612 vos_close(pVosContext);
4613
Jeff Johnson295189b2012-06-20 16:38:30 -07004614 //Close Watchdog
4615 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4616 vos_watchdog_close(pVosContext);
4617
4618 /* Cancel the vote for XO Core ON.
4619 * This is done here to ensure there is no race condition since MC, TX and WD threads have
4620 * exited at this point
4621 */
4622 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
4623 " when WLAN is turned OFF\n");
4624 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4625 {
4626 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
4627 " Not returning failure."
4628 " Power consumed will be high\n");
4629 }
4630
4631 hdd_close_all_adapters( pHddCtx );
4632
4633
4634 //Free up dynamically allocated members inside HDD Adapter
4635 kfree(pHddCtx->cfg_ini);
4636 pHddCtx->cfg_ini= NULL;
4637
4638 /* free the power on lock from platform driver */
4639 if (free_riva_power_on_lock("wlan"))
4640 {
4641 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
4642 __func__);
4643 }
4644
Jeff Johnson88ba7742013-02-27 14:36:02 -08004645free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08004646 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004647 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004648 if (hdd_is_ssr_required())
4649 {
4650 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07004651 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07004652 msleep(5000);
4653 }
4654 hdd_set_ssr_required (VOS_FALSE);
4655}
4656
4657
4658/**---------------------------------------------------------------------------
4659
4660 \brief hdd_update_config_from_nv() - Function to update the contents of
4661 the running configuration with parameters taken from NV storage
4662
4663 \param - pHddCtx - Pointer to the HDD global context
4664
4665 \return - VOS_STATUS_SUCCESS if successful
4666
4667 --------------------------------------------------------------------------*/
4668static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
4669{
Jeff Johnson295189b2012-06-20 16:38:30 -07004670 v_BOOL_t itemIsValid = VOS_FALSE;
4671 VOS_STATUS status;
4672 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
4673 v_U8_t macLoop;
4674
4675 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
4676 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
4677 if(status != VOS_STATUS_SUCCESS)
4678 {
4679 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
4680 return VOS_STATUS_E_FAILURE;
4681 }
4682
4683 if (itemIsValid == VOS_TRUE)
4684 {
4685 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
4686 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
4687 VOS_MAX_CONCURRENCY_PERSONA);
4688 if(status != VOS_STATUS_SUCCESS)
4689 {
4690 /* Get MAC from NV fail, not update CFG info
4691 * INI MAC value will be used for MAC setting */
4692 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
4693 return VOS_STATUS_E_FAILURE;
4694 }
4695
4696 /* If first MAC is not valid, treat all others are not valid
4697 * Then all MACs will be got from ini file */
4698 if(vos_is_macaddr_zero(&macFromNV[0]))
4699 {
4700 /* MAC address in NV file is not configured yet */
4701 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
4702 return VOS_STATUS_E_INVAL;
4703 }
4704
4705 /* Get MAC address from NV, update CFG info */
4706 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
4707 {
4708 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
4709 {
4710 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
4711 /* This MAC is not valid, skip it
4712 * This MAC will be got from ini file */
4713 }
4714 else
4715 {
4716 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
4717 (v_U8_t *)&macFromNV[macLoop].bytes[0],
4718 VOS_MAC_ADDR_SIZE);
4719 }
4720 }
4721 }
4722 else
4723 {
4724 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
4725 return VOS_STATUS_E_FAILURE;
4726 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004727
Jeff Johnson295189b2012-06-20 16:38:30 -07004728
4729 return VOS_STATUS_SUCCESS;
4730}
4731
4732/**---------------------------------------------------------------------------
4733
4734 \brief hdd_post_voss_start_config() - HDD post voss start config helper
4735
4736 \param - pAdapter - Pointer to the HDD
4737
4738 \return - None
4739
4740 --------------------------------------------------------------------------*/
4741VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
4742{
4743 eHalStatus halStatus;
4744 v_U32_t listenInterval;
4745
Jeff Johnson295189b2012-06-20 16:38:30 -07004746
4747 // Send ready indication to the HDD. This will kick off the MAC
4748 // into a 'running' state and should kick off an initial scan.
4749 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
4750 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4751 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304752 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07004753 "code %08d [x%08x]",__func__, halStatus, halStatus );
4754 return VOS_STATUS_E_FAILURE;
4755 }
4756
4757 // Set default LI into HDD context,
4758 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
4759 // And RIVA will crash
4760 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
4761 pHddCtx->hdd_actual_LI_value = listenInterval;
4762
4763 return VOS_STATUS_SUCCESS;
4764}
4765
Jeff Johnson295189b2012-06-20 16:38:30 -07004766/* wake lock APIs for HDD */
4767void hdd_prevent_suspend(void)
4768{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004769#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004770 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004771#else
4772 wcnss_prevent_suspend();
4773#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004774}
4775
4776void hdd_allow_suspend(void)
4777{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004778#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004779 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004780#else
4781 wcnss_allow_suspend();
4782#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004783}
4784
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004785void hdd_allow_suspend_timeout(v_U32_t timeout)
4786{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004787#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07004788 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004789#else
4790 /* Do nothing as there is no API in wcnss for timeout*/
4791#endif
4792}
4793
Jeff Johnson295189b2012-06-20 16:38:30 -07004794/**---------------------------------------------------------------------------
4795
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004796 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
4797 information between Host and Riva
4798
4799 This function gets reported version of FW
4800 It also finds the version of Riva headers used to compile the host
4801 It compares the above two and prints a warning if they are different
4802 It gets the SW and HW version string
4803 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
4804 indicating the features they support through a bitmap
4805
4806 \param - pHddCtx - Pointer to HDD context
4807
4808 \return - void
4809
4810 --------------------------------------------------------------------------*/
4811
4812void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
4813{
4814
4815 tSirVersionType versionCompiled;
4816 tSirVersionType versionReported;
4817 tSirVersionString versionString;
4818 tANI_U8 fwFeatCapsMsgSupported = 0;
4819 VOS_STATUS vstatus;
4820
4821 /* retrieve and display WCNSS version information */
4822 do {
4823
4824 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
4825 &versionCompiled);
4826 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4827 {
4828 hddLog(VOS_TRACE_LEVEL_FATAL,
4829 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004830 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004831 break;
4832 }
4833
4834 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
4835 &versionReported);
4836 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4837 {
4838 hddLog(VOS_TRACE_LEVEL_FATAL,
4839 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004840 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004841 break;
4842 }
4843
4844 if ((versionCompiled.major != versionReported.major) ||
4845 (versionCompiled.minor != versionReported.minor) ||
4846 (versionCompiled.version != versionReported.version) ||
4847 (versionCompiled.revision != versionReported.revision))
4848 {
4849 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4850 "Host expected %u.%u.%u.%u\n",
4851 WLAN_MODULE_NAME,
4852 (int)versionReported.major,
4853 (int)versionReported.minor,
4854 (int)versionReported.version,
4855 (int)versionReported.revision,
4856 (int)versionCompiled.major,
4857 (int)versionCompiled.minor,
4858 (int)versionCompiled.version,
4859 (int)versionCompiled.revision);
4860 }
4861 else
4862 {
4863 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4864 WLAN_MODULE_NAME,
4865 (int)versionReported.major,
4866 (int)versionReported.minor,
4867 (int)versionReported.version,
4868 (int)versionReported.revision);
4869 }
4870
4871 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
4872 versionString,
4873 sizeof(versionString));
4874 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4875 {
4876 hddLog(VOS_TRACE_LEVEL_FATAL,
4877 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004878 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004879 break;
4880 }
4881
4882 pr_info("%s: WCNSS software version %s\n",
4883 WLAN_MODULE_NAME, versionString);
4884
4885 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
4886 versionString,
4887 sizeof(versionString));
4888 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4889 {
4890 hddLog(VOS_TRACE_LEVEL_FATAL,
4891 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004892 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004893 break;
4894 }
4895
4896 pr_info("%s: WCNSS hardware version %s\n",
4897 WLAN_MODULE_NAME, versionString);
4898
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004899 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
4900 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004901 send the message only if it the riva is 1.1
4902 minor numbers for different riva branches:
4903 0 -> (1.0)Mainline Build
4904 1 -> (1.1)Mainline Build
4905 2->(1.04) Stability Build
4906 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004907 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004908 ((versionReported.minor>=1) && (versionReported.version>=1)))
4909 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
4910 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004911
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004912 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08004913 {
4914#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4915 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
4916 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
4917#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004918 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08004919 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004920
4921 } while (0);
4922
4923}
4924
4925/**---------------------------------------------------------------------------
4926
Jeff Johnson295189b2012-06-20 16:38:30 -07004927 \brief hdd_wlan_startup() - HDD init function
4928
4929 This is the driver startup code executed once a WLAN device has been detected
4930
4931 \param - dev - Pointer to the underlying device
4932
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004933 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07004934
4935 --------------------------------------------------------------------------*/
4936
4937int hdd_wlan_startup(struct device *dev )
4938{
4939 VOS_STATUS status;
4940 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004941 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004942 hdd_context_t *pHddCtx = NULL;
4943 v_CONTEXT_t pVosContext= NULL;
4944#ifdef WLAN_BTAMP_FEATURE
4945 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
4946 WLANBAP_ConfigType btAmpConfig;
4947 hdd_config_t *pConfig;
4948#endif
4949 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07004950 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004951
4952 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07004953 /*
4954 * cfg80211: wiphy allocation
4955 */
4956 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
4957
4958 if(wiphy == NULL)
4959 {
4960 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004961 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004962 }
4963
4964 pHddCtx = wiphy_priv(wiphy);
4965
Jeff Johnson295189b2012-06-20 16:38:30 -07004966 //Initialize the adapter context to zeros.
4967 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
4968
Jeff Johnson295189b2012-06-20 16:38:30 -07004969 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004970 hdd_prevent_suspend();
4971 pHddCtx->isLoadUnloadInProgress = TRUE;
4972
4973 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4974
4975 /*Get vos context here bcoz vos_open requires it*/
4976 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4977
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08004978 if(pVosContext == NULL)
4979 {
4980 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
4981 goto err_free_hdd_context;
4982 }
4983
Jeff Johnson295189b2012-06-20 16:38:30 -07004984 //Save the Global VOSS context in adapter context for future.
4985 pHddCtx->pvosContext = pVosContext;
4986
4987 //Save the adapter context in global context for future.
4988 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
4989
Jeff Johnson295189b2012-06-20 16:38:30 -07004990 pHddCtx->parent_dev = dev;
4991
4992 init_completion(&pHddCtx->full_pwr_comp_var);
4993 init_completion(&pHddCtx->standby_comp_var);
4994 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004995 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004996 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004997
4998 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
4999
5000 // Load all config first as TL config is needed during vos_open
5001 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5002 if(pHddCtx->cfg_ini == NULL)
5003 {
5004 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5005 goto err_free_hdd_context;
5006 }
5007
5008 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5009
5010 // Read and parse the qcom_cfg.ini file
5011 status = hdd_parse_config_ini( pHddCtx );
5012 if ( VOS_STATUS_SUCCESS != status )
5013 {
5014 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5015 __func__, WLAN_INI_FILE);
5016 goto err_config;
5017 }
5018
Jeff Johnson295189b2012-06-20 16:38:30 -07005019 /*
5020 * cfg80211: Initialization and registration ...
5021 */
5022 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
5023 {
5024 hddLog(VOS_TRACE_LEVEL_FATAL,
5025 "%s: wlan_hdd_cfg80211_register return failure", __func__);
5026 goto err_wiphy_reg;
5027 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005028
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005029 // Update VOS trace levels based upon the cfg.ini
5030 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5031 pHddCtx->cfg_ini->vosTraceEnableBAP);
5032 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5033 pHddCtx->cfg_ini->vosTraceEnableTL);
5034 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5035 pHddCtx->cfg_ini->vosTraceEnableWDI);
5036 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5037 pHddCtx->cfg_ini->vosTraceEnableHDD);
5038 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5039 pHddCtx->cfg_ini->vosTraceEnableSME);
5040 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5041 pHddCtx->cfg_ini->vosTraceEnablePE);
5042 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5043 pHddCtx->cfg_ini->vosTraceEnableWDA);
5044 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5045 pHddCtx->cfg_ini->vosTraceEnableSYS);
5046 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5047 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005048 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5049 pHddCtx->cfg_ini->vosTraceEnableSAP);
5050 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5051 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005052
Jeff Johnson295189b2012-06-20 16:38:30 -07005053 // Update WDI trace levels based upon the cfg.ini
5054 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5055 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5056 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5057 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5058 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5059 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5060 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5061 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005062
Jeff Johnson88ba7742013-02-27 14:36:02 -08005063 if (VOS_FTM_MODE == hdd_get_conparam())
5064 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005065 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5066 {
5067 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5068 goto err_free_hdd_context;
5069 }
5070 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5071 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005072 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005073
Jeff Johnson88ba7742013-02-27 14:36:02 -08005074 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005075 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5076 {
5077 status = vos_watchdog_open(pVosContext,
5078 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5079
5080 if(!VOS_IS_STATUS_SUCCESS( status ))
5081 {
5082 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005083 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005084 }
5085 }
5086
5087 pHddCtx->isLogpInProgress = FALSE;
5088 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5089
Jeff Johnson295189b2012-06-20 16:38:30 -07005090 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5091 if(!VOS_IS_STATUS_SUCCESS(status))
5092 {
5093 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005094 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005095 }
5096
Jeff Johnson295189b2012-06-20 16:38:30 -07005097 status = vos_open( &pVosContext, 0);
5098 if ( !VOS_IS_STATUS_SUCCESS( status ))
5099 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005100 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5101 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005102 }
5103
Jeff Johnson295189b2012-06-20 16:38:30 -07005104 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5105
5106 if ( NULL == pHddCtx->hHal )
5107 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005108 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005109 goto err_vosclose;
5110 }
5111
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005112 status = vos_preStart( pHddCtx->pvosContext );
5113 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5114 {
5115 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5116 goto err_vosclose;
5117 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005118
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005119 /* Note that the vos_preStart() sequence triggers the cfg download.
5120 The cfg download must occur before we update the SME config
5121 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005122 status = hdd_set_sme_config( pHddCtx );
5123
5124 if ( VOS_STATUS_SUCCESS != status )
5125 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005126 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5127 goto err_vosclose;
5128 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005129
5130 //Initialize the WMM module
5131 status = hdd_wmm_init(pHddCtx);
5132 if (!VOS_IS_STATUS_SUCCESS(status))
5133 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005134 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005135 goto err_vosclose;
5136 }
5137
Jeff Johnson295189b2012-06-20 16:38:30 -07005138 /* In the integrated architecture we update the configuration from
5139 the INI file and from NV before vOSS has been started so that
5140 the final contents are available to send down to the cCPU */
5141
5142 // Apply the cfg.ini to cfg.dat
5143 if (FALSE == hdd_update_config_dat(pHddCtx))
5144 {
5145 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5146 goto err_vosclose;
5147 }
5148
5149 // Apply the NV to cfg.dat
5150 /* Prima Update MAC address only at here */
5151 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5152 {
5153#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5154 /* There was not a valid set of MAC Addresses in NV. See if the
5155 default addresses were modified by the cfg.ini settings. If so,
5156 we'll use them, but if not, we'll autogenerate a set of MAC
5157 addresses based upon the device serial number */
5158
5159 static const v_MACADDR_t default_address =
5160 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5161 unsigned int serialno;
5162 int i;
5163
5164 serialno = wcnss_get_serial_number();
5165 if ((0 != serialno) &&
5166 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5167 sizeof(default_address))))
5168 {
5169 /* cfg.ini has the default address, invoke autogen logic */
5170
5171 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5172 bytes of the serial number that can be used to generate
5173 the other 3 bytes of the MAC address. Mask off all but
5174 the lower 3 bytes (this will also make sure we don't
5175 overflow in the next step) */
5176 serialno &= 0x00FFFFFF;
5177
5178 /* we need a unique address for each session */
5179 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5180
5181 /* autogen all addresses */
5182 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5183 {
5184 /* start with the entire default address */
5185 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5186 /* then replace the lower 3 bytes */
5187 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5188 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5189 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5190
5191 serialno++;
5192 }
5193
5194 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5195 MAC_ADDRESS_STR,
5196 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5197 }
5198 else
5199#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5200 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005201 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005202 "%s: Invalid MAC address in NV, using MAC from ini file "
5203 MAC_ADDRESS_STR, __func__,
5204 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5205 }
5206 }
5207 {
5208 eHalStatus halStatus;
5209 // Set the MAC Address
5210 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5211 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5212 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5213 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5214
5215 if (!HAL_STATUS_SUCCESS( halStatus ))
5216 {
5217 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5218 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005219 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005220 }
5221 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005222
5223 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5224 Note: Firmware image will be read and downloaded inside vos_start API */
5225 status = vos_start( pHddCtx->pvosContext );
5226 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5227 {
5228 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5229 goto err_vosclose;
5230 }
5231
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005232 /* Exchange capability info between Host and FW and also get versioning info from FW */
5233 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005234
5235 status = hdd_post_voss_start_config( pHddCtx );
5236 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5237 {
5238 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5239 __func__);
5240 goto err_vosstop;
5241 }
5242
Jeff Johnson295189b2012-06-20 16:38:30 -07005243 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5244 {
5245 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5246 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5247 }
5248 else
5249 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005250 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5251 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5252 if (pAdapter != NULL)
5253 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305254 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005255 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305256 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5257 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5258 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005259
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305260 /* Generate the P2P Device Address. This consists of the device's
5261 * primary MAC address with the locally administered bit set.
5262 */
5263 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005264 }
5265 else
5266 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305267 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5268 if (p2p_dev_addr != NULL)
5269 {
5270 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5271 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5272 }
5273 else
5274 {
5275 hddLog(VOS_TRACE_LEVEL_FATAL,
5276 "%s: Failed to allocate mac_address for p2p_device",
5277 __func__);
5278 goto err_close_adapter;
5279 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005280 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005281
5282 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5283 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5284 if ( NULL == pP2pAdapter )
5285 {
5286 hddLog(VOS_TRACE_LEVEL_FATAL,
5287 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005288 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005289 goto err_close_adapter;
5290 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005291 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005292 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005293
5294 if( pAdapter == NULL )
5295 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005296 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5297 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005298 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005299
Jeff Johnson295189b2012-06-20 16:38:30 -07005300#ifdef WLAN_BTAMP_FEATURE
5301 vStatus = WLANBAP_Open(pVosContext);
5302 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5303 {
5304 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5305 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005306 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005307 }
5308
5309 vStatus = BSL_Init(pVosContext);
5310 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5311 {
5312 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5313 "%s: Failed to Init BSL",__func__);
5314 goto err_bap_close;
5315 }
5316 vStatus = WLANBAP_Start(pVosContext);
5317 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5318 {
5319 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5320 "%s: Failed to start TL",__func__);
5321 goto err_bap_close;
5322 }
5323
5324 pConfig = pHddCtx->cfg_ini;
5325 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5326 status = WLANBAP_SetConfig(&btAmpConfig);
5327
5328#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005329
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005330#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5331 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5332 {
5333 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5334 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5335 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5336 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5337 }
5338#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005339#ifdef FEATURE_WLAN_SCAN_PNO
5340 /*SME must send channel update configuration to RIVA*/
5341 sme_UpdateChannelConfig(pHddCtx->hHal);
5342#endif
5343
Jeff Johnson295189b2012-06-20 16:38:30 -07005344 /* Register with platform driver as client for Suspend/Resume */
5345 status = hddRegisterPmOps(pHddCtx);
5346 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5347 {
5348 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5349#ifdef WLAN_BTAMP_FEATURE
5350 goto err_bap_stop;
5351#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005352 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005353#endif //WLAN_BTAMP_FEATURE
5354 }
5355
5356 /* Register TM level change handler function to the platform */
5357 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5358 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5359 {
5360 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5361 goto err_unregister_pmops;
5362 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005363
5364 /* register for riva power on lock to platform driver */
5365 if (req_riva_power_on_lock("wlan"))
5366 {
5367 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5368 __func__);
5369 goto err_unregister_pmops;
5370 }
5371
Jeff Johnson295189b2012-06-20 16:38:30 -07005372 // register net device notifier for device change notification
5373 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5374
5375 if(ret < 0)
5376 {
5377 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5378 goto err_free_power_on_lock;
5379 }
5380
5381 //Initialize the nlink service
5382 if(nl_srv_init() != 0)
5383 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305384 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005385 goto err_reg_netdev;
5386 }
5387
5388 //Initialize the BTC service
5389 if(btc_activate_service(pHddCtx) != 0)
5390 {
5391 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5392 goto err_nl_srv;
5393 }
5394
5395#ifdef PTT_SOCK_SVC_ENABLE
5396 //Initialize the PTT service
5397 if(ptt_sock_activate_svc(pHddCtx) != 0)
5398 {
5399 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5400 goto err_nl_srv;
5401 }
5402#endif
5403
Jeff Johnson295189b2012-06-20 16:38:30 -07005404 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005405 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005406 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005407 /* Action frame registered in one adapter which will
5408 * applicable to all interfaces
5409 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005410 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005411 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005412
5413 mutex_init(&pHddCtx->sap_lock);
5414
5415 pHddCtx->isLoadUnloadInProgress = FALSE;
5416
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005417#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005418#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5419 /* Initialize the wake lcok */
5420 wake_lock_init(&pHddCtx->rx_wake_lock,
5421 WAKE_LOCK_SUSPEND,
5422 "qcom_rx_wakelock");
5423#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005424 /* Initialize the wake lcok */
5425 wake_lock_init(&pHddCtx->sap_wake_lock,
5426 WAKE_LOCK_SUSPEND,
5427 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005428#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005429
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005430 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5431 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005432
5433 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5434 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005435
5436 // Initialize the restart logic
5437 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305438
Jeff Johnson295189b2012-06-20 16:38:30 -07005439 goto success;
5440
5441err_nl_srv:
5442 nl_srv_exit();
5443
5444err_reg_netdev:
5445 unregister_netdevice_notifier(&hdd_netdev_notifier);
5446
5447err_free_power_on_lock:
5448 free_riva_power_on_lock("wlan");
5449
5450err_unregister_pmops:
5451 hddDevTmUnregisterNotifyCallback(pHddCtx);
5452 hddDeregisterPmOps(pHddCtx);
5453
5454#ifdef WLAN_BTAMP_FEATURE
5455err_bap_stop:
5456 WLANBAP_Stop(pVosContext);
5457#endif
5458
5459#ifdef WLAN_BTAMP_FEATURE
5460err_bap_close:
5461 WLANBAP_Close(pVosContext);
5462#endif
5463
Jeff Johnson295189b2012-06-20 16:38:30 -07005464err_close_adapter:
5465 hdd_close_all_adapters( pHddCtx );
5466
5467err_vosstop:
5468 vos_stop(pVosContext);
5469
5470err_vosclose:
5471 status = vos_sched_close( pVosContext );
5472 if (!VOS_IS_STATUS_SUCCESS(status)) {
5473 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5474 "%s: Failed to close VOSS Scheduler", __func__);
5475 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5476 }
5477 vos_close(pVosContext );
5478
Jeff Johnson295189b2012-06-20 16:38:30 -07005479err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005480 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005481
5482err_wdclose:
5483 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5484 vos_watchdog_close(pVosContext);
5485
Jeff Johnson295189b2012-06-20 16:38:30 -07005486err_wiphy_reg:
5487 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005488
5489err_config:
5490 kfree(pHddCtx->cfg_ini);
5491 pHddCtx->cfg_ini= NULL;
5492
5493err_free_hdd_context:
5494 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005495 wiphy_free(wiphy) ;
5496 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005497 VOS_BUG(1);
5498
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005499 if (hdd_is_ssr_required())
5500 {
5501 /* WDI timeout had happened during load, so SSR is needed here */
5502 subsystem_restart("wcnss");
5503 msleep(5000);
5504 }
5505 hdd_set_ssr_required (VOS_FALSE);
5506
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005507 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005508
5509success:
5510 EXIT();
5511 return 0;
5512}
5513
5514/**---------------------------------------------------------------------------
5515
Jeff Johnson32d95a32012-09-10 13:15:23 -07005516 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07005517
Jeff Johnson32d95a32012-09-10 13:15:23 -07005518 This is the driver entry point - called in different timeline depending
5519 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07005520
5521 \param - None
5522
5523 \return - 0 for success, non zero for failure
5524
5525 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07005526static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005527{
5528 VOS_STATUS status;
5529 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005530 struct device *dev = NULL;
5531 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005532#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5533 int max_retries = 0;
5534#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005535
5536 ENTER();
5537
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005538#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005539 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07005540#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005541
5542 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
5543 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
5544
5545 //Power Up Libra WLAN card first if not already powered up
5546 status = vos_chipPowerUp(NULL,NULL,NULL);
5547 if (!VOS_IS_STATUS_SUCCESS(status))
5548 {
5549 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
5550 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005551 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005552 }
5553
Jeff Johnson295189b2012-06-20 16:38:30 -07005554#ifdef ANI_BUS_TYPE_PCI
5555
5556 dev = wcnss_wlan_get_device();
5557
5558#endif // ANI_BUS_TYPE_PCI
5559
5560#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005561
5562#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5563 /* wait until WCNSS driver downloads NV */
5564 while (!wcnss_device_ready() && 5 >= ++max_retries) {
5565 msleep(1000);
5566 }
5567 if (max_retries >= 5) {
5568 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
5569 return -ENODEV;
5570 }
5571#endif
5572
Jeff Johnson295189b2012-06-20 16:38:30 -07005573 dev = wcnss_wlan_get_device();
5574#endif // ANI_BUS_TYPE_PLATFORM
5575
5576
5577 do {
5578 if (NULL == dev) {
5579 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
5580 ret_status = -1;
5581 break;
5582 }
5583
5584#ifdef MEMORY_DEBUG
5585 vos_mem_init();
5586#endif
5587
5588#ifdef TIMER_MANAGER
5589 vos_timer_manager_init();
5590#endif
5591
5592 /* Preopen VOSS so that it is ready to start at least SAL */
5593 status = vos_preOpen(&pVosContext);
5594
5595 if (!VOS_IS_STATUS_SUCCESS(status))
5596 {
5597 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
5598 ret_status = -1;
5599 break;
5600 }
5601
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005602#ifndef MODULE
5603 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
5604 */
5605 hdd_set_conparam((v_UINT_t)con_mode);
5606#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005607
5608 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005609 if (hdd_wlan_startup(dev))
5610 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005611 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005612 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005613 vos_preClose( &pVosContext );
5614 ret_status = -1;
5615 break;
5616 }
5617
5618 /* Cancel the vote for XO Core ON
5619 * This is done here for safety purposes in case we re-initialize without turning
5620 * it OFF in any error scenario.
5621 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005622 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07005623 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005624 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07005625 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5626 {
5627 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
5628 " Power consumed will be high\n");
5629 }
5630 } while (0);
5631
5632 if (0 != ret_status)
5633 {
5634 //Assert Deep sleep signal now to put Libra HW in lowest power state
5635 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5636 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
5637
5638 //Vote off any PMIC voltage supplies
5639 vos_chipPowerDown(NULL, NULL, NULL);
5640#ifdef TIMER_MANAGER
5641 vos_timer_exit();
5642#endif
5643#ifdef MEMORY_DEBUG
5644 vos_mem_exit();
5645#endif
5646
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005647#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005648 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005649#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005650 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
5651 }
5652 else
5653 {
5654 //Send WLAN UP indication to Nlink Service
5655 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
5656
5657 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
5658
5659 }
5660
5661 EXIT();
5662
5663 return ret_status;
5664}
5665
Jeff Johnson32d95a32012-09-10 13:15:23 -07005666/**---------------------------------------------------------------------------
5667
5668 \brief hdd_module_init() - Init Function
5669
5670 This is the driver entry point (invoked when module is loaded using insmod)
5671
5672 \param - None
5673
5674 \return - 0 for success, non zero for failure
5675
5676 --------------------------------------------------------------------------*/
5677#ifdef MODULE
5678static int __init hdd_module_init ( void)
5679{
5680 return hdd_driver_init();
5681}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005682#else /* #ifdef MODULE */
5683static int __init hdd_module_init ( void)
5684{
5685 /* Driver initialization is delayed to fwpath_changed_handler */
5686 return 0;
5687}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005688#endif /* #ifdef MODULE */
5689
Jeff Johnson295189b2012-06-20 16:38:30 -07005690
5691/**---------------------------------------------------------------------------
5692
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005693 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005694
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005695 This is the driver exit point (invoked when module is unloaded using rmmod
5696 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07005697
5698 \param - None
5699
5700 \return - None
5701
5702 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005703static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005704{
5705 hdd_context_t *pHddCtx = NULL;
5706 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005707
5708 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
5709
5710 //Get the global vos context
5711 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5712
5713 if(!pVosContext)
5714 {
5715 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
5716 goto done;
5717 }
5718
5719 //Get the HDD context.
5720 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
5721
5722 if(!pHddCtx)
5723 {
5724 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
5725 }
5726 else
5727 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005728 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07005729 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07005730 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
5731 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07005732 }
5733
5734 pHddCtx->isLoadUnloadInProgress = TRUE;
5735 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5736
5737 //Do all the cleanup before deregistering the driver
5738 hdd_wlan_exit(pHddCtx);
5739 }
5740
Jeff Johnson295189b2012-06-20 16:38:30 -07005741 vos_preClose( &pVosContext );
5742
5743#ifdef TIMER_MANAGER
5744 vos_timer_exit();
5745#endif
5746#ifdef MEMORY_DEBUG
5747 vos_mem_exit();
5748#endif
5749
5750done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005751#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005752 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005753#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005754 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
5755}
5756
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005757/**---------------------------------------------------------------------------
5758
5759 \brief hdd_module_exit() - Exit function
5760
5761 This is the driver exit point (invoked when module is unloaded using rmmod)
5762
5763 \param - None
5764
5765 \return - None
5766
5767 --------------------------------------------------------------------------*/
5768static void __exit hdd_module_exit(void)
5769{
5770 hdd_driver_exit();
5771}
5772
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005773#ifdef MODULE
5774static int fwpath_changed_handler(const char *kmessage,
5775 struct kernel_param *kp)
5776{
Jeff Johnson76052702013-04-16 13:55:05 -07005777 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005778}
5779
5780static int con_mode_handler(const char *kmessage,
5781 struct kernel_param *kp)
5782{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07005783 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005784}
5785#else /* #ifdef MODULE */
5786/**---------------------------------------------------------------------------
5787
Jeff Johnson76052702013-04-16 13:55:05 -07005788 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005789
Jeff Johnson76052702013-04-16 13:55:05 -07005790 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005791 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07005792 - invoked when module parameter fwpath is modified from userspace to signal
5793 initializing the WLAN driver or when con_mode is modified from userspace
5794 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005795
5796 \return - 0 for success, non zero for failure
5797
5798 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07005799static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005800{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005801 int ret_status;
5802
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005803 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005804 ret_status = hdd_driver_init();
5805 wlan_hdd_inited = ret_status ? 0 : 1;
5806 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005807 }
5808
5809 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07005810
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005811 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07005812
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005813 ret_status = hdd_driver_init();
5814 wlan_hdd_inited = ret_status ? 0 : 1;
5815 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005816}
5817
Jeff Johnson295189b2012-06-20 16:38:30 -07005818/**---------------------------------------------------------------------------
5819
Jeff Johnson76052702013-04-16 13:55:05 -07005820 \brief fwpath_changed_handler() - Handler Function
5821
5822 Handle changes to the fwpath parameter
5823
5824 \return - 0 for success, non zero for failure
5825
5826 --------------------------------------------------------------------------*/
5827static int fwpath_changed_handler(const char *kmessage,
5828 struct kernel_param *kp)
5829{
5830 int ret;
5831
5832 ret = param_set_copystring(kmessage, kp);
5833 if (0 == ret)
5834 ret = kickstart_driver();
5835 return ret;
5836}
5837
5838/**---------------------------------------------------------------------------
5839
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005840 \brief con_mode_handler() -
5841
5842 Handler function for module param con_mode when it is changed by userspace
5843 Dynamically linked - do nothing
5844 Statically linked - exit and init driver, as in rmmod and insmod
5845
Jeff Johnson76052702013-04-16 13:55:05 -07005846 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005847
Jeff Johnson76052702013-04-16 13:55:05 -07005848 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005849
5850 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07005851static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005852{
Jeff Johnson76052702013-04-16 13:55:05 -07005853 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005854
Jeff Johnson76052702013-04-16 13:55:05 -07005855 ret = param_set_int(kmessage, kp);
5856 if (0 == ret)
5857 ret = kickstart_driver();
5858 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005859}
5860#endif /* #ifdef MODULE */
5861
5862/**---------------------------------------------------------------------------
5863
Jeff Johnson295189b2012-06-20 16:38:30 -07005864 \brief hdd_get_conparam() -
5865
5866 This is the driver exit point (invoked when module is unloaded using rmmod)
5867
5868 \param - None
5869
5870 \return - tVOS_CON_MODE
5871
5872 --------------------------------------------------------------------------*/
5873tVOS_CON_MODE hdd_get_conparam ( void )
5874{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005875#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07005876 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005877#else
5878 return (tVOS_CON_MODE)curr_con_mode;
5879#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005880}
5881void hdd_set_conparam ( v_UINT_t newParam )
5882{
5883 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005884#ifndef MODULE
5885 curr_con_mode = con_mode;
5886#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005887}
5888/**---------------------------------------------------------------------------
5889
5890 \brief hdd_softap_sta_deauth() - function
5891
5892 This to take counter measure to handle deauth req from HDD
5893
5894 \param - pAdapter - Pointer to the HDD
5895
5896 \param - enable - boolean value
5897
5898 \return - None
5899
5900 --------------------------------------------------------------------------*/
5901
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005902VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07005903{
Jeff Johnson295189b2012-06-20 16:38:30 -07005904 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005905 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07005906
5907 ENTER();
5908
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305909 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07005910
5911 //Ignore request to deauth bcmc station
5912 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005913 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005914
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005915 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07005916
5917 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005918 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005919}
5920
5921/**---------------------------------------------------------------------------
5922
5923 \brief hdd_softap_sta_disassoc() - function
5924
5925 This to take counter measure to handle deauth req from HDD
5926
5927 \param - pAdapter - Pointer to the HDD
5928
5929 \param - enable - boolean value
5930
5931 \return - None
5932
5933 --------------------------------------------------------------------------*/
5934
5935void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
5936{
5937 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5938
5939 ENTER();
5940
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305941 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07005942
5943 //Ignore request to disassoc bcmc station
5944 if( pDestMacAddress[0] & 0x1 )
5945 return;
5946
5947 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
5948}
5949
5950void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
5951{
5952 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5953
5954 ENTER();
5955
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305956 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07005957
5958 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
5959}
5960
Jeff Johnson295189b2012-06-20 16:38:30 -07005961/**---------------------------------------------------------------------------
5962 *
5963 * \brief hdd_get__concurrency_mode() -
5964 *
5965 *
5966 * \param - None
5967 *
5968 * \return - CONCURRENCY MODE
5969 *
5970 * --------------------------------------------------------------------------*/
5971tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
5972{
5973 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5974 hdd_context_t *pHddCtx;
5975
5976 if (NULL != pVosContext)
5977 {
5978 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5979 if (NULL != pHddCtx)
5980 {
5981 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
5982 }
5983 }
5984
5985 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005986 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005987 return VOS_STA;
5988}
5989
5990/* Decide whether to allow/not the apps power collapse.
5991 * Allow apps power collapse if we are in connected state.
5992 * if not, allow only if we are in IMPS */
5993v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
5994{
5995 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08005996 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005997 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07005998 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5999 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6000 hdd_adapter_t *pAdapter = NULL;
6001 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006002 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006003
Jeff Johnson295189b2012-06-20 16:38:30 -07006004 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6005 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006006
Yathish9f22e662012-12-10 14:21:35 -08006007 concurrent_state = hdd_get_concurrency_mode();
6008
6009#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6010 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6011 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6012 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6013 return TRUE;
6014#endif
6015
Jeff Johnson295189b2012-06-20 16:38:30 -07006016 /*loop through all adapters. TBD fix for Concurrency */
6017 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6018 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6019 {
6020 pAdapter = pAdapterNode->pAdapter;
6021 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6022 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6023 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006024 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006025 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006026 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006027 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6028 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006029 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006030 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006031 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6032 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006033 return FALSE;
6034 }
6035 }
6036 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6037 pAdapterNode = pNext;
6038 }
6039 return TRUE;
6040}
6041
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006042/* Decides whether to send suspend notification to Riva
6043 * if any adapter is in BMPS; then it is required */
6044v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6045{
6046 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6047 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6048
6049 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6050 {
6051 return TRUE;
6052 }
6053 return FALSE;
6054}
6055
Jeff Johnson295189b2012-06-20 16:38:30 -07006056void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6057{
6058 switch(mode)
6059 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006060 case VOS_STA_MODE:
6061 case VOS_P2P_CLIENT_MODE:
6062 case VOS_P2P_GO_MODE:
6063 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006064 pHddCtx->concurrency_mode |= (1 << mode);
6065 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006066 break;
6067 default:
6068 break;
6069
6070 }
6071 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6072 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6073}
6074
6075
6076void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6077{
6078 switch(mode)
6079 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006080 case VOS_STA_MODE:
6081 case VOS_P2P_CLIENT_MODE:
6082 case VOS_P2P_GO_MODE:
6083 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006084 pHddCtx->no_of_sessions[mode]--;
6085 if (!(pHddCtx->no_of_sessions[mode]))
6086 pHddCtx->concurrency_mode &= (~(1 << mode));
6087 break;
6088 default:
6089 break;
6090 }
6091 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6092 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6093}
6094
Jeff Johnsone7245742012-09-05 17:12:55 -07006095/**---------------------------------------------------------------------------
6096 *
6097 * \brief wlan_hdd_restart_init
6098 *
6099 * This function initalizes restart timer/flag. An internal function.
6100 *
6101 * \param - pHddCtx
6102 *
6103 * \return - None
6104 *
6105 * --------------------------------------------------------------------------*/
6106
6107static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6108{
6109 /* Initialize */
6110 pHddCtx->hdd_restart_retries = 0;
6111 atomic_set(&pHddCtx->isRestartInProgress, 0);
6112 vos_timer_init(&pHddCtx->hdd_restart_timer,
6113 VOS_TIMER_TYPE_SW,
6114 wlan_hdd_restart_timer_cb,
6115 pHddCtx);
6116}
6117/**---------------------------------------------------------------------------
6118 *
6119 * \brief wlan_hdd_restart_deinit
6120 *
6121 * This function cleans up the resources used. An internal function.
6122 *
6123 * \param - pHddCtx
6124 *
6125 * \return - None
6126 *
6127 * --------------------------------------------------------------------------*/
6128
6129static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6130{
6131
6132 VOS_STATUS vos_status;
6133 /* Block any further calls */
6134 atomic_set(&pHddCtx->isRestartInProgress, 1);
6135 /* Cleanup */
6136 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6137 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006138 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006139 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6140 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006141 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006142
6143}
6144
6145/**---------------------------------------------------------------------------
6146 *
6147 * \brief wlan_hdd_framework_restart
6148 *
6149 * This function uses a cfg80211 API to start a framework initiated WLAN
6150 * driver module unload/load.
6151 *
6152 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6153 *
6154 *
6155 * \param - pHddCtx
6156 *
6157 * \return - VOS_STATUS_SUCCESS: Success
6158 * VOS_STATUS_E_EMPTY: Adapter is Empty
6159 * VOS_STATUS_E_NOMEM: No memory
6160
6161 * --------------------------------------------------------------------------*/
6162
6163static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6164{
6165 VOS_STATUS status = VOS_STATUS_SUCCESS;
6166 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006167 int len = (sizeof (struct ieee80211_mgmt));
6168 struct ieee80211_mgmt *mgmt = NULL;
6169
6170 /* Prepare the DEAUTH managment frame with reason code */
6171 mgmt = kzalloc(len, GFP_KERNEL);
6172 if(mgmt == NULL)
6173 {
6174 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6175 "%s: memory allocation failed (%d bytes)", __func__, len);
6176 return VOS_STATUS_E_NOMEM;
6177 }
6178 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006179
6180 /* Iterate over all adapters/devices */
6181 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6182 do
6183 {
6184 if( (status == VOS_STATUS_SUCCESS) &&
6185 pAdapterNode &&
6186 pAdapterNode->pAdapter)
6187 {
6188 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6189 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6190 pAdapterNode->pAdapter->dev->name,
6191 pAdapterNode->pAdapter->device_mode,
6192 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006193 /*
6194 * CFG80211 event to restart the driver
6195 *
6196 * 'cfg80211_send_unprot_deauth' sends a
6197 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6198 * of SME(Linux Kernel) state machine.
6199 *
6200 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6201 * the driver.
6202 *
6203 */
6204
6205 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006206 }
6207 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6208 pAdapterNode = pNext;
6209 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6210
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006211
6212 /* Free the allocated management frame */
6213 kfree(mgmt);
6214
Jeff Johnsone7245742012-09-05 17:12:55 -07006215 /* Retry until we unload or reach max count */
6216 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6217 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6218
6219 return status;
6220
6221}
6222/**---------------------------------------------------------------------------
6223 *
6224 * \brief wlan_hdd_restart_timer_cb
6225 *
6226 * Restart timer callback. An internal function.
6227 *
6228 * \param - User data:
6229 *
6230 * \return - None
6231 *
6232 * --------------------------------------------------------------------------*/
6233
6234void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6235{
6236 hdd_context_t *pHddCtx = usrDataForCallback;
6237 wlan_hdd_framework_restart(pHddCtx);
6238 return;
6239
6240}
6241
6242
6243/**---------------------------------------------------------------------------
6244 *
6245 * \brief wlan_hdd_restart_driver
6246 *
6247 * This function sends an event to supplicant to restart the WLAN driver.
6248 *
6249 * This function is called from vos_wlanRestart.
6250 *
6251 * \param - pHddCtx
6252 *
6253 * \return - VOS_STATUS_SUCCESS: Success
6254 * VOS_STATUS_E_EMPTY: Adapter is Empty
6255 * VOS_STATUS_E_ALREADY: Request already in progress
6256
6257 * --------------------------------------------------------------------------*/
6258VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6259{
6260 VOS_STATUS status = VOS_STATUS_SUCCESS;
6261
6262 /* A tight check to make sure reentrancy */
6263 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6264 {
6265 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6266 "%s: WLAN restart is already in progress", __func__);
6267
6268 return VOS_STATUS_E_ALREADY;
6269 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006270 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006271#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006272 wcnss_reset_intr();
6273#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006274
Jeff Johnsone7245742012-09-05 17:12:55 -07006275 return status;
6276}
6277
6278
Jeff Johnson295189b2012-06-20 16:38:30 -07006279//Register the module init/exit functions
6280module_init(hdd_module_init);
6281module_exit(hdd_module_exit);
6282
6283MODULE_LICENSE("Dual BSD/GPL");
6284MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6285MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6286
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006287module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6288 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006289
Jeff Johnson76052702013-04-16 13:55:05 -07006290module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006291 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);