blob: 448866e3b55946a4f05f46dbdcd752da4e3db5a0 [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 */
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800163#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700164static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700165#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700166/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700167static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700168
169//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700170static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
171static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
172static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
173void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800174void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700175
Jeff Johnson295189b2012-06-20 16:38:30 -0700176v_U16_t hdd_select_queue(struct net_device *dev,
177 struct sk_buff *skb);
178
179#ifdef WLAN_FEATURE_PACKET_FILTERING
180static void hdd_set_multicast_list(struct net_device *dev);
181#endif
182
183void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700184int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700185
186extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800187#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
188void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
189static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
190static VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700191static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
192 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
193 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800194#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700195static int hdd_netdev_notifier_call(struct notifier_block * nb,
196 unsigned long state,
197 void *ndev)
198{
199 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700200 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700201 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700202#ifdef WLAN_BTAMP_FEATURE
203 VOS_STATUS status;
204 hdd_context_t *pHddCtx;
205#endif
206
207 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700208 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700209 (strncmp(dev->name, "p2p", 3)))
210 return NOTIFY_DONE;
211
212 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700213 return NOTIFY_DONE;
214
Jeff Johnson295189b2012-06-20 16:38:30 -0700215 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700216 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700217
Jeff Johnson27cee452013-03-27 11:10:24 -0700218 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700219 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800220 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700221 VOS_ASSERT(0);
222 return NOTIFY_DONE;
223 }
224
Jeff Johnson27cee452013-03-27 11:10:24 -0700225 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
226 if (NULL == pHddCtx)
227 {
228 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
229 VOS_ASSERT(0);
230 return NOTIFY_DONE;
231 }
232
233 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
234 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700235
236 switch (state) {
237 case NETDEV_REGISTER:
238 break;
239
240 case NETDEV_UNREGISTER:
241 break;
242
243 case NETDEV_UP:
244 break;
245
246 case NETDEV_DOWN:
247 break;
248
249 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700250 if(TRUE == pAdapter->isLinkUpSvcNeeded)
251 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700252 break;
253
254 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700255 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700256 {
257 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800258 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700259 hdd_abort_mac_scan(pAdapter->pHddCtx);
260 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800261 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700262 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
263 if(!result)
264 {
265 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800266 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700267 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700268 }
269 }
270 else
271 {
272 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700273 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700274 }
275#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700276 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700277 status = WLANBAP_StopAmp();
278 if(VOS_STATUS_SUCCESS != status )
279 {
280 pHddCtx->isAmpAllowed = VOS_TRUE;
281 hddLog(VOS_TRACE_LEVEL_FATAL,
282 "%s: Failed to stop AMP", __func__);
283 }
284 else
285 {
286 //a state m/c implementation in PAL is TBD to avoid this delay
287 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700288 if ( pHddCtx->isAmpAllowed )
289 {
290 WLANBAP_DeregisterFromHCI();
291 pHddCtx->isAmpAllowed = VOS_FALSE;
292 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700293 }
294#endif //WLAN_BTAMP_FEATURE
295 break;
296
297 default:
298 break;
299 }
300
301 return NOTIFY_DONE;
302}
303
304struct notifier_block hdd_netdev_notifier = {
305 .notifier_call = hdd_netdev_notifier_call,
306};
307
308/*---------------------------------------------------------------------------
309 * Function definitions
310 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700311void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
312void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700313//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700314static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700315#ifndef MODULE
316/* current con_mode - used only for statically linked driver
317 * con_mode is changed by userspace to indicate a mode change which will
318 * result in calling the module exit and init functions. The module
319 * exit function will clean up based on the value of con_mode prior to it
320 * being changed by userspace. So curr_con_mode records the current con_mode
321 * for exit when con_mode becomes the next mode for init
322 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700323static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700324#endif
325
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800326/**---------------------------------------------------------------------------
327
328 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
329
330 Called immediately after the cfg.ini is read in order to configure
331 the desired trace levels.
332
333 \param - moduleId - module whose trace level is being configured
334 \param - bitmask - bitmask of log levels to be enabled
335
336 \return - void
337
338 --------------------------------------------------------------------------*/
339static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
340{
341 wpt_tracelevel level;
342
343 /* if the bitmask is the default value, then a bitmask was not
344 specified in cfg.ini, so leave the logging level alone (it
345 will remain at the "compiled in" default value) */
346 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
347 {
348 return;
349 }
350
351 /* a mask was specified. start by disabling all logging */
352 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
353
354 /* now cycle through the bitmask until all "set" bits are serviced */
355 level = VOS_TRACE_LEVEL_FATAL;
356 while (0 != bitmask)
357 {
358 if (bitmask & 1)
359 {
360 vos_trace_setValue(moduleId, level, 1);
361 }
362 level++;
363 bitmask >>= 1;
364 }
365}
366
367
Jeff Johnson295189b2012-06-20 16:38:30 -0700368/**---------------------------------------------------------------------------
369
370 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
371
372 Called immediately after the cfg.ini is read in order to configure
373 the desired trace levels in the WDI.
374
375 \param - moduleId - module whose trace level is being configured
376 \param - bitmask - bitmask of log levels to be enabled
377
378 \return - void
379
380 --------------------------------------------------------------------------*/
381static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
382{
383 wpt_tracelevel level;
384
385 /* if the bitmask is the default value, then a bitmask was not
386 specified in cfg.ini, so leave the logging level alone (it
387 will remain at the "compiled in" default value) */
388 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
389 {
390 return;
391 }
392
393 /* a mask was specified. start by disabling all logging */
394 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
395
396 /* now cycle through the bitmask until all "set" bits are serviced */
397 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
398 while (0 != bitmask)
399 {
400 if (bitmask & 1)
401 {
402 wpalTraceSetLevel(moduleId, level, 1);
403 }
404 level++;
405 bitmask >>= 1;
406 }
407}
Jeff Johnson295189b2012-06-20 16:38:30 -0700408
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530409void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
410{
411 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
412 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
413 hdd_config_t *cfg_param;
414 eCsrPhyMode phyMode;
415
416 if (NULL == pHddCtx)
417 {
418 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
419 "HDD Context is null !!");
420 return ;
421 }
422
423 cfg_param = pHddCtx->cfg_ini;
424
425 if (NULL == cfg_param)
426 {
427 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
428 "cfg_params not available !!");
429 return ;
430 }
431
432 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
433
434 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
435 {
436 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
437 (eCSR_DOT11_MODE_11ac == phyMode) ||
438 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
439 {
440 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
441 "Setting phymode to 11n!!");
442 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
443 }
444 }
445 else
446 {
447 /*New country Supports 11ac as well resetting value back from .ini*/
448 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
449 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
450 return ;
451 }
452
453 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
454 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
455 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
456 {
457 VOS_STATUS vosStatus;
458
459 // need to issue a disconnect to CSR.
460 INIT_COMPLETION(pAdapter->disconnect_comp_var);
461 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
462 pAdapter->sessionId,
463 eCSR_DISCONNECT_REASON_UNSPECIFIED );
464
465 if (VOS_STATUS_SUCCESS == vosStatus)
466 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
467 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
468
469 }
470}
471
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700472void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
473{
474 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
475 hdd_config_t *cfg_param;
476
477 if (NULL == pHddCtx)
478 {
479 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
480 "HDD Context is null !!");
481 return ;
482 }
483
484 cfg_param = pHddCtx->cfg_ini;
485
486 if (NULL == cfg_param)
487 {
488 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
489 "cfg_params not available !!");
490 return ;
491 }
492
493 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
494 {
495 /*New country doesn't support DFS */
496 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
497 }
498 else
499 {
500 /*New country Supports DFS as well resetting value back from .ini*/
501 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
502 }
503
504}
505
Jeff Johnson295189b2012-06-20 16:38:30 -0700506int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
507{
508 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
509 hdd_priv_data_t priv_data;
510 tANI_U8 *command = NULL;
511 int ret = 0;
512
513 if (NULL == pAdapter)
514 {
515 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700516 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700517 ret = -ENODEV;
518 goto exit;
519 }
520
Jeff Johnsone7245742012-09-05 17:12:55 -0700521 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700522 {
523 ret = -EINVAL;
524 goto exit;
525 }
526
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -0700527 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
528 {
529 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
530 "%s:LOGP in Progress. Ignore!!!", __func__);
531 ret = -EBUSY;
532 goto exit;
533 }
534
Jeff Johnson295189b2012-06-20 16:38:30 -0700535 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
536 {
537 ret = -EFAULT;
538 goto exit;
539 }
540
541 command = kmalloc(priv_data.total_len, GFP_KERNEL);
542 if (!command)
543 {
544 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700545 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700546 ret = -ENOMEM;
547 goto exit;
548 }
549
550 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
551 {
552 ret = -EFAULT;
553 goto exit;
554 }
555
556 if ((SIOCDEVPRIVATE + 1) == cmd)
557 {
558 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
559
560 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700561 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700562
563 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
564 {
565 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
566 sizeof(tSirMacAddr)))
567 {
568 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700569 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700570 ret = -EFAULT;
571 }
572 }
Amar Singhal0974e402013-02-12 14:27:46 -0800573 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700574 {
Amar Singhal0974e402013-02-12 14:27:46 -0800575 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700576 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800577
Jeff Johnson295189b2012-06-20 16:38:30 -0700578 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800579
580 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700581 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700582 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800583 "%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 -0700584 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800585 ret = hdd_setBand_helper(dev, ptr);
586 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700587 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
588 {
589 char *country_code;
590
591 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700592
593 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530594 hdd_checkandupdate_phymode(pAdapter, country_code);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700595 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
596 pAdapter, pHddCtx->pvosContext);
597 if( 0 != ret )
598 {
599 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
600 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
601
602 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700603 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800604#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
605 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
606 {
607 tANI_U8 *value = command;
608 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
609 tANI_U8 revision = 0;
610 eHalStatus status = eHAL_STATUS_SUCCESS;
611 v_REGDOMAIN_t regId;
612
613 status = hdd_parse_countryrev(value, countryCode, &revision);
614 if (eHAL_STATUS_SUCCESS != status)
615 {
616 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
617 "%s: Failed to parse country revision information", __func__);
618 ret = -EINVAL;
619 goto exit;
620 }
621
622 /* Validate country code */
623 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
624 if (eHAL_STATUS_SUCCESS != status)
625 {
626 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
627 "%s: Invalid country code %s", __func__, countryCode);
628 ret = -EINVAL;
629 goto exit;
630 }
631
632 /* Validate revision */
633 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
634 {
635 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
636 "%s: Invalid revision %d", __func__, revision);
637 ret = -EINVAL;
638 goto exit;
639 }
640
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700641 hdd_checkandupdate_dfssetting(pAdapter, countryCode);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530642 hdd_checkandupdate_phymode(pAdapter, countryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800643 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
644 pAdapter, pHddCtx->pvosContext);
645 if (0 != ret)
646 {
647 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
648 "%s: SME Change Country code fail ret=%d", __func__, ret);
649 ret = -EINVAL;
650 goto exit;
651 }
652
653 if (0 == strncmp(countryCode, "KR", 2))
654 {
655 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
656 revision);
657 if (eHAL_STATUS_SUCCESS != status)
658 {
659 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
660 "%s: Failed to build valid channel list", __func__);
661 ret = -EINVAL;
662 goto exit;
663 }
664 }
665 }
666#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700667 /*
668 command should be a string having format
669 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
670 */
Amar Singhal0974e402013-02-12 14:27:46 -0800671 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700672 {
Amar Singhal0974e402013-02-12 14:27:46 -0800673 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700674
675 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700676 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700677
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800678 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700679 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800680 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
681 {
682 int suspend = 0;
683 tANI_U8 *ptr = (tANI_U8*)command + 15;
684
685 suspend = *ptr - '0';
686 hdd_set_wlan_suspend_mode(suspend);
687 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800688#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
689 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
690 {
691 tANI_U8 *value = command;
692 int rssi = 0;
693 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
694 eHalStatus status = eHAL_STATUS_SUCCESS;
695
696 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
697 value = value + 15;
698
699 sscanf(value, "%d", &rssi);
700 lookUpThreshold = abs(rssi);
701 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
702 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
703 {
704 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
705 "Neighbor lookup threshold value %d is out of range"
706 " (Min: %d Max: %d)", lookUpThreshold,
707 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
708 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
709 ret = -EINVAL;
710 goto exit;
711 }
712
713 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
714 "%s: Received Command to Set Roam trigger"
715 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
716
717 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
718 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
719 if (eHAL_STATUS_SUCCESS != status)
720 {
721 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
722 "%s: Failed to set roam trigger, try again", __func__);
723 ret = -EPERM;
724 goto exit;
725 }
726
727 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
728 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
729 }
730 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
731 {
732 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
733 int rssi = (-1) * lookUpThreshold;
734 char extra[32];
735 tANI_U8 len = 0;
736
737 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
738 if (copy_to_user(priv_data.buf, &extra, len + 1))
739 {
740 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
741 "%s: failed to copy data to user buffer", __func__);
742 ret = -EFAULT;
743 goto exit;
744 }
745 }
746 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
747 {
748 tANI_U8 *value = command;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700749 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800750 /* input refresh period is in terms of seconds */
751 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
752 value = value + 18;
753 /* Convert the value from ascii to integer */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700754 ret = kstrtou16(value, 10, &neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800755 if (ret < 0)
756 {
757 /* If the input value is greater than max value of datatype, then also
758 kstrtou16 fails */
759 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
760 "%s: kstrtou16 failed ",
761 "Input value may be out of range[%d - %d]",
762 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700763 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
764 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800765 ret = -EINVAL;
766 goto exit;
767 }
768
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700769 neighborEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod * 1000;
770 if ((neighborEmptyScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
771 (neighborEmptyScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800772 {
773 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700774 "Neighbor empty scan results refresh period value %d is out of range"
775 " (Min: %d Max: %d)", neighborEmptyScanRefreshPeriod/1000,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700776 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
777 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800778 ret = -EINVAL;
779 goto exit;
780 }
781
782 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
783 "%s: Received Command to Set roam scan period"
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700784 " (Empty Scan refresh period) = %d", __func__, neighborEmptyScanRefreshPeriod/1000);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800785
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700786 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
787 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800788 }
789 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
790 {
791 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
792 char extra[32];
793 tANI_U8 len = 0;
794
795 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
796 /* Returned value is in units of seconds */
797 if (copy_to_user(priv_data.buf, &extra, len + 1))
798 {
799 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
800 "%s: failed to copy data to user buffer", __func__);
801 ret = -EFAULT;
802 goto exit;
803 }
804 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700805 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
806 {
807 tANI_U8 *value = command;
808 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
809 /* input refresh period is in terms of seconds */
810 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
811 value = value + 25;
812 /* Convert the value from ascii to integer */
813 ret = kstrtou16(value, 10, &neighborScanRefreshPeriod);
814 if (ret < 0)
815 {
816 /* If the input value is greater than max value of datatype, then also
817 kstrtou16 fails */
818 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
819 "%s: kstrtou16 failed ",
820 "Input value may be out of range[%d - %d]",
821 __func__,
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700822 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
823 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700824 ret = -EINVAL;
825 goto exit;
826 }
827
828 neighborScanRefreshPeriod = neighborScanRefreshPeriod * 1000;
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700829 if ((neighborScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
830 (neighborScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700831 {
832 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
833 "Neighbor scan results refresh period value %d is out of range"
834 " (Min: %d Max: %d)", neighborScanRefreshPeriod/1000,
835 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
836 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
837 ret = -EINVAL;
838 goto exit;
839 }
840
841 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
842 "%s: Received Command to Set roam scan refresh period"
843 " (Scan refresh period) = %d", __func__, neighborScanRefreshPeriod/1000);
844
845 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
846 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
847 }
848 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
849 {
850 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
851 char extra[32];
852 tANI_U8 len = 0;
853
854 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
855 /* Returned value is in units of seconds */
856 if (copy_to_user(priv_data.buf, &extra, len + 1))
857 {
858 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
859 "%s: failed to copy data to user buffer", __func__);
860 ret = -EFAULT;
861 goto exit;
862 }
863 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800864#endif
865#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
866 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
867 {
868 tANI_U8 *value = command;
869 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
870
871 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
872 value = value + 13;
873 /* Convert the value from ascii to integer */
874 ret = kstrtou8(value, 10, &roamRssiDiff);
875 if (ret < 0)
876 {
877 /* If the input value is greater than max value of datatype, then also
878 kstrtou8 fails */
879 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
880 "%s: kstrtou8 failed range [%d - %d]", __func__,
881 CFG_ROAM_RSSI_DIFF_MIN,
882 CFG_ROAM_RSSI_DIFF_MAX);
883 ret = -EINVAL;
884 goto exit;
885 }
886
887 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
888 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
889 {
890 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
891 "Roam rssi diff value %d is out of range"
892 " (Min: %d Max: %d)", roamRssiDiff,
893 CFG_ROAM_RSSI_DIFF_MIN,
894 CFG_ROAM_RSSI_DIFF_MAX);
895 ret = -EINVAL;
896 goto exit;
897 }
898
899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
900 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
901
902 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
903 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
904 }
905 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
906 {
907 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
908 char extra[32];
909 tANI_U8 len = 0;
910
911 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
912 if (copy_to_user(priv_data.buf, &extra, len + 1))
913 {
914 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
915 "%s: failed to copy data to user buffer", __func__);
916 ret = -EFAULT;
917 goto exit;
918 }
919 }
920#endif
921#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
922 else if (strncmp(command, "GETBAND", 7) == 0)
923 {
924 int band = -1;
925 char extra[32];
926 tANI_U8 len = 0;
927 hdd_getBand_helper(pHddCtx, &band);
928
929 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
930 if (copy_to_user(priv_data.buf, &extra, len + 1))
931 {
932 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
933 "%s: failed to copy data to user buffer", __func__);
934 ret = -EFAULT;
935 goto exit;
936 }
937 }
938 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
939 {
940 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
941 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
942 tANI_U8 revision = 0;
943 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
944 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
945 char extra[32] = {0};
946 tANI_U8 len = 0;
947
948 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
949 {
950 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
951 "%s: failed to get country code", __func__);
952 ret = -EFAULT;
953 goto exit;
954 }
955 pBuf[uBufLen] = '\0';
956 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
957
958 if (0 == strncmp(pBuf, "KR", 2))
959 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
960 else
961 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
962
963 if (copy_to_user(priv_data.buf, &extra, len + 1))
964 {
965 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
966 "%s: failed to copy data to user buffer", __func__);
967 ret = -EFAULT;
968 goto exit;
969 }
970 }
971 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
972 {
973 tANI_U8 *value = command;
974 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
975 tANI_U8 numChannels = 0;
976 eHalStatus status = eHAL_STATUS_SUCCESS;
977
978 status = hdd_parse_channellist(value, ChannelList, &numChannels);
979 if (eHAL_STATUS_SUCCESS != status)
980 {
981 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
982 "%s: Failed to parse channel list information", __func__);
983 ret = -EINVAL;
984 goto exit;
985 }
986
987 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
988 {
989 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
990 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
991 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
992 ret = -EINVAL;
993 goto exit;
994 }
995 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
996 numChannels);
997 if (eHAL_STATUS_SUCCESS != status)
998 {
999 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1000 "%s: Failed to update channel list information", __func__);
1001 ret = -EINVAL;
1002 goto exit;
1003 }
1004 }
1005 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
1006 {
1007 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1008 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07001009 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001010 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07001011 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001012
1013 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
1014 ChannelList, &numChannels ))
1015 {
1016 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1017 "%s: failed to get roam scan channel list", __func__);
1018 ret = -EFAULT;
1019 goto exit;
1020 }
1021 /* output channel list is of the format
1022 [Number of roam scan channels][Channel1][Channel2]... */
1023 /* copy the number of channels in the 0th index */
1024 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
1025 for (j = 0; (j < numChannels); j++)
1026 {
1027 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
1028 }
1029
1030 if (copy_to_user(priv_data.buf, &extra, len + 1))
1031 {
1032 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1033 "%s: failed to copy data to user buffer", __func__);
1034 ret = -EFAULT;
1035 goto exit;
1036 }
1037 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001038 else if (strncmp(command, "GETCCXMODE", 10) == 0)
1039 {
1040 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1041 char extra[32];
1042 tANI_U8 len = 0;
1043
1044 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
1045 if (copy_to_user(priv_data.buf, &extra, len + 1))
1046 {
1047 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1048 "%s: failed to copy data to user buffer", __func__);
1049 ret = -EFAULT;
1050 goto exit;
1051 }
1052 }
1053 else if (strncmp(command, "GETOKCMODE", 10) == 0)
1054 {
1055 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
1056 char extra[32];
1057 tANI_U8 len = 0;
1058
1059 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
1060 if (copy_to_user(priv_data.buf, &extra, len + 1))
1061 {
1062 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1063 "%s: failed to copy data to user buffer", __func__);
1064 ret = -EFAULT;
1065 goto exit;
1066 }
1067 }
1068 else if (strncmp(command, "GETFASTROAM", 10) == 0)
1069 {
1070 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1071 char extra[32];
1072 tANI_U8 len = 0;
1073
1074 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
1075 if (copy_to_user(priv_data.buf, &extra, len + 1))
1076 {
1077 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1078 "%s: failed to copy data to user buffer", __func__);
1079 ret = -EFAULT;
1080 goto exit;
1081 }
1082 }
1083 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
1084 {
1085 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1086 char extra[32];
1087 tANI_U8 len = 0;
1088
1089 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
1090 if (copy_to_user(priv_data.buf, &extra, len + 1))
1091 {
1092 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1093 "%s: failed to copy data to user buffer", __func__);
1094 ret = -EFAULT;
1095 goto exit;
1096 }
1097 }
1098 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
1099 {
1100 tANI_U8 *value = command;
1101 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1102
1103 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1104 value = value + 26;
1105 /* Convert the value from ascii to integer */
1106 ret = kstrtou8(value, 10, &minTime);
1107 if (ret < 0)
1108 {
1109 /* If the input value is greater than max value of datatype, then also
1110 kstrtou8 fails */
1111 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1112 "%s: kstrtou8 failed range [%d - %d]", __func__,
1113 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1114 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1115 ret = -EINVAL;
1116 goto exit;
1117 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001118 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1119 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1120 {
1121 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1122 "scan min channel time value %d is out of range"
1123 " (Min: %d Max: %d)", minTime,
1124 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1125 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1126 ret = -EINVAL;
1127 goto exit;
1128 }
1129
1130 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1131 "%s: Received Command to change channel min time = %d", __func__, minTime);
1132
1133 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1134 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1135 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001136 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1137 {
1138 tANI_U8 *value = command;
1139 tANI_U8 channel = 0;
1140 tANI_U8 dwellTime = 0;
1141 tANI_U8 bufLen = 0;
1142 tANI_U8 *buf = NULL;
1143 tSirMacAddr targetApBssid;
1144 eHalStatus status = eHAL_STATUS_SUCCESS;
1145 struct ieee80211_channel chan;
1146 tANI_U8 finalLen = 0;
1147 tANI_U8 *finalBuf = NULL;
1148 tANI_U8 temp = 0;
1149 u64 cookie;
1150 hdd_station_ctx_t *pHddStaCtx = NULL;
1151 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1152
1153 /* if not associated, no need to send action frame */
1154 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1155 {
1156 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1157 ret = -EINVAL;
1158 goto exit;
1159 }
1160
1161 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1162 &dwellTime, &buf, &bufLen);
1163 if (eHAL_STATUS_SUCCESS != status)
1164 {
1165 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1166 "%s: Failed to parse send action frame data", __func__);
1167 ret = -EINVAL;
1168 goto exit;
1169 }
1170
1171 /* if the target bssid is different from currently associated AP,
1172 then no need to send action frame */
1173 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1174 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1175 {
1176 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1177 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001178 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001179 goto exit;
1180 }
1181
1182 /* if the channel number is different from operating channel then
1183 no need to send action frame */
1184 if (channel != pHddStaCtx->conn_info.operationChannel)
1185 {
1186 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1187 "%s: channel(%d) is different from operating channel(%d)",
1188 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1189 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001190 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001191 goto exit;
1192 }
1193 chan.center_freq = sme_ChnToFreq(channel);
1194
1195 finalLen = bufLen + 24;
1196 finalBuf = vos_mem_malloc(finalLen);
1197 if (NULL == finalBuf)
1198 {
1199 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1200 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001201 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001202 goto exit;
1203 }
1204 vos_mem_zero(finalBuf, finalLen);
1205
1206 /* Fill subtype */
1207 temp = SIR_MAC_MGMT_ACTION << 4;
1208 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1209
1210 /* Fill type */
1211 temp = SIR_MAC_MGMT_FRAME;
1212 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1213
1214 /* Fill destination address (bssid of the AP) */
1215 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1216
1217 /* Fill BSSID (STA mac address) */
1218 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1219
1220 /* Fill source address (STA mac address) */
1221 vos_mem_copy(finalBuf + 16, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1222
1223 /* Fill received buffer from 24th address */
1224 vos_mem_copy(finalBuf + 24, buf, bufLen);
1225
Jeff Johnson11c33152013-04-16 17:52:40 -07001226 /* done with the parsed buffer */
1227 vos_mem_free(buf);
1228
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001229 wlan_hdd_action( NULL, dev, &chan, 0, NL80211_CHAN_HT20,
1230 1, dwellTime, finalBuf, finalLen, 1,
1231 1, &cookie );
1232 vos_mem_free(finalBuf);
1233 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001234 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1235 {
1236 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1237 char extra[32];
1238 tANI_U8 len = 0;
1239
1240 /* value is interms of msec */
1241 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1242 if (copy_to_user(priv_data.buf, &extra, len + 1))
1243 {
1244 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1245 "%s: failed to copy data to user buffer", __func__);
1246 ret = -EFAULT;
1247 goto exit;
1248 }
1249 }
1250 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1251 {
1252 tANI_U8 *value = command;
1253 tANI_U8 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
1254
1255 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1256 value = value + 19;
1257 /* Convert the value from ascii to integer */
1258 ret = kstrtou8(value, 10, &maxTime);
1259 if (ret < 0)
1260 {
1261 /* If the input value is greater than max value of datatype, then also
1262 kstrtou8 fails */
1263 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1264 "%s: kstrtou8 failed range [%d - %d]", __func__,
1265 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1266 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1267 ret = -EINVAL;
1268 goto exit;
1269 }
1270
1271 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1272 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1273 {
1274 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1275 "lfr mode value %d is out of range"
1276 " (Min: %d Max: %d)", maxTime,
1277 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1278 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1279 ret = -EINVAL;
1280 goto exit;
1281 }
1282
1283 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1284 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1285
1286 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
1287 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1288 }
1289 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1290 {
1291 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1292 char extra[32];
1293 tANI_U8 len = 0;
1294
1295 /* value is interms of msec */
1296 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1297 if (copy_to_user(priv_data.buf, &extra, len + 1))
1298 {
1299 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1300 "%s: failed to copy data to user buffer", __func__);
1301 ret = -EFAULT;
1302 goto exit;
1303 }
1304 }
1305 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1306 {
1307 tANI_U8 *value = command;
1308 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1309
1310 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1311 value = value + 16;
1312 /* Convert the value from ascii to integer */
1313 ret = kstrtou16(value, 10, &val);
1314 if (ret < 0)
1315 {
1316 /* If the input value is greater than max value of datatype, then also
1317 kstrtou16 fails */
1318 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1319 "%s: kstrtou16 failed range [%d - %d]", __func__,
1320 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1321 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1322 ret = -EINVAL;
1323 goto exit;
1324 }
1325
1326 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1327 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1328 {
1329 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1330 "scan home time value %d is out of range"
1331 " (Min: %d Max: %d)", val,
1332 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1333 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1334 ret = -EINVAL;
1335 goto exit;
1336 }
1337
1338 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1339 "%s: Received Command to change scan home time = %d", __func__, val);
1340
1341 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1342 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1343 }
1344 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1345 {
1346 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1347 char extra[32];
1348 tANI_U8 len = 0;
1349
1350 /* value is interms of msec */
1351 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1352 if (copy_to_user(priv_data.buf, &extra, len + 1))
1353 {
1354 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1355 "%s: failed to copy data to user buffer", __func__);
1356 ret = -EFAULT;
1357 goto exit;
1358 }
1359 }
1360 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1361 {
1362 tANI_U8 *value = command;
1363 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1364
1365 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1366 value = value + 17;
1367 /* Convert the value from ascii to integer */
1368 ret = kstrtou8(value, 10, &val);
1369 if (ret < 0)
1370 {
1371 /* If the input value is greater than max value of datatype, then also
1372 kstrtou8 fails */
1373 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1374 "%s: kstrtou8 failed range [%d - %d]", __func__,
1375 CFG_ROAM_INTRA_BAND_MIN,
1376 CFG_ROAM_INTRA_BAND_MAX);
1377 ret = -EINVAL;
1378 goto exit;
1379 }
1380
1381 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1382 (val > CFG_ROAM_INTRA_BAND_MAX))
1383 {
1384 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1385 "intra band mode value %d is out of range"
1386 " (Min: %d Max: %d)", val,
1387 CFG_ROAM_INTRA_BAND_MIN,
1388 CFG_ROAM_INTRA_BAND_MAX);
1389 ret = -EINVAL;
1390 goto exit;
1391 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001392 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1393 "%s: Received Command to change intra band = %d", __func__, val);
1394
1395 pHddCtx->cfg_ini->nRoamIntraBand = val;
1396 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1397 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001398 else if (strncmp(command, "SETWESMODE", 10) == 0)
1399 {
1400 tANI_U8 *value = command;
1401 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
1402
1403 /* Move pointer to ahead of SETWESMODE<delimiter> */
1404 value = value + 11;
1405 /* Convert the value from ascii to integer */
1406 ret = kstrtou8(value, 10, &wesMode);
1407 if (ret < 0)
1408 {
1409 /* If the input value is greater than max value of datatype, then also
1410 kstrtou8 fails */
1411 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1412 "%s: kstrtou8 failed range [%d - %d]", __func__,
1413 CFG_ENABLE_WES_MODE_NAME_MIN,
1414 CFG_ENABLE_WES_MODE_NAME_MAX);
1415 ret = -EINVAL;
1416 goto exit;
1417 }
1418
1419 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
1420 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
1421 {
1422 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1423 "WES Mode value %d is out of range"
1424 " (Min: %d Max: %d)", wesMode,
1425 CFG_ENABLE_WES_MODE_NAME_MIN,
1426 CFG_ENABLE_WES_MODE_NAME_MAX);
1427 ret = -EINVAL;
1428 goto exit;
1429 }
1430 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1431 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
1432
1433 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
1434 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
1435 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001436 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1437 {
1438 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1439 char extra[32];
1440 tANI_U8 len = 0;
1441
1442 /* value is interms of msec */
1443 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1444 if (copy_to_user(priv_data.buf, &extra, len + 1))
1445 {
1446 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1447 "%s: failed to copy data to user buffer", __func__);
1448 ret = -EFAULT;
1449 goto exit;
1450 }
1451 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001452 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
1453 {
1454 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
1455 char extra[32];
1456 tANI_U8 len = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001457
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001458 len = snprintf(extra, sizeof(extra), "%s %d", command, wesMode);
1459 if (copy_to_user(priv_data.buf, &extra, len + 1))
1460 {
1461 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1462 "%s: failed to copy data to user buffer", __func__);
1463 ret = -EFAULT;
1464 goto exit;
1465 }
1466 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001467#endif
1468#ifdef FEATURE_WLAN_LFR
1469 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1470 {
1471 tANI_U8 *value = command;
1472 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1473
1474 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1475 value = value + 12;
1476 /* Convert the value from ascii to integer */
1477 ret = kstrtou8(value, 10, &lfrMode);
1478 if (ret < 0)
1479 {
1480 /* If the input value is greater than max value of datatype, then also
1481 kstrtou8 fails */
1482 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1483 "%s: kstrtou8 failed range [%d - %d]", __func__,
1484 CFG_LFR_FEATURE_ENABLED_MIN,
1485 CFG_LFR_FEATURE_ENABLED_MAX);
1486 ret = -EINVAL;
1487 goto exit;
1488 }
1489
1490 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1491 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1492 {
1493 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1494 "lfr mode value %d is out of range"
1495 " (Min: %d Max: %d)", lfrMode,
1496 CFG_LFR_FEATURE_ENABLED_MIN,
1497 CFG_LFR_FEATURE_ENABLED_MAX);
1498 ret = -EINVAL;
1499 goto exit;
1500 }
1501
1502 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1503 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1504
1505 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1506 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1507 }
1508#endif
1509#ifdef WLAN_FEATURE_VOWIFI_11R
1510 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1511 {
1512 tANI_U8 *value = command;
1513 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1514
1515 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1516 value = value + 18;
1517 /* Convert the value from ascii to integer */
1518 ret = kstrtou8(value, 10, &ft);
1519 if (ret < 0)
1520 {
1521 /* If the input value is greater than max value of datatype, then also
1522 kstrtou8 fails */
1523 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1524 "%s: kstrtou8 failed range [%d - %d]", __func__,
1525 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1526 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1527 ret = -EINVAL;
1528 goto exit;
1529 }
1530
1531 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1532 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1533 {
1534 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1535 "ft mode value %d is out of range"
1536 " (Min: %d Max: %d)", ft,
1537 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1538 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1539 ret = -EINVAL;
1540 goto exit;
1541 }
1542
1543 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1544 "%s: Received Command to change ft mode = %d", __func__, ft);
1545
1546 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1547 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1548 }
1549#endif
1550#ifdef FEATURE_WLAN_CCX
1551 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1552 {
1553 tANI_U8 *value = command;
1554 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1555
1556 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1557 value = value + 11;
1558 /* Convert the value from ascii to integer */
1559 ret = kstrtou8(value, 10, &ccxMode);
1560 if (ret < 0)
1561 {
1562 /* If the input value is greater than max value of datatype, then also
1563 kstrtou8 fails */
1564 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1565 "%s: kstrtou8 failed range [%d - %d]", __func__,
1566 CFG_CCX_FEATURE_ENABLED_MIN,
1567 CFG_CCX_FEATURE_ENABLED_MAX);
1568 ret = -EINVAL;
1569 goto exit;
1570 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001571 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1572 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1573 {
1574 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1575 "Ccx mode value %d is out of range"
1576 " (Min: %d Max: %d)", ccxMode,
1577 CFG_CCX_FEATURE_ENABLED_MIN,
1578 CFG_CCX_FEATURE_ENABLED_MAX);
1579 ret = -EINVAL;
1580 goto exit;
1581 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001582 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1583 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1584
1585 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1586 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1587 }
1588#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001589 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1590 {
1591 tANI_U8 *value = command;
1592 tANI_BOOLEAN roamScanControl = 0;
1593
1594 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1595 value = value + 19;
1596 /* Convert the value from ascii to integer */
1597 ret = kstrtou8(value, 10, &roamScanControl);
1598 if (ret < 0)
1599 {
1600 /* If the input value is greater than max value of datatype, then also
1601 kstrtou8 fails */
1602 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1603 "%s: kstrtou8 failed ", __func__);
1604 ret = -EINVAL;
1605 goto exit;
1606 }
1607
1608 if (0 != roamScanControl)
1609 {
1610 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1611 "roam scan control invalid value = %d",
1612 roamScanControl);
1613 ret = -EINVAL;
1614 goto exit;
1615 }
1616 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1617 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1618
1619 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1620 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001621#ifdef FEATURE_WLAN_OKC
1622 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1623 {
1624 tANI_U8 *value = command;
1625 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1626
1627 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1628 value = value + 11;
1629 /* Convert the value from ascii to integer */
1630 ret = kstrtou8(value, 10, &okcMode);
1631 if (ret < 0)
1632 {
1633 /* If the input value is greater than max value of datatype, then also
1634 kstrtou8 fails */
1635 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1636 "%s: kstrtou8 failed range [%d - %d]", __func__,
1637 CFG_OKC_FEATURE_ENABLED_MIN,
1638 CFG_OKC_FEATURE_ENABLED_MAX);
1639 ret = -EINVAL;
1640 goto exit;
1641 }
1642
1643 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1644 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1645 {
1646 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1647 "Okc mode value %d is out of range"
1648 " (Min: %d Max: %d)", okcMode,
1649 CFG_OKC_FEATURE_ENABLED_MIN,
1650 CFG_OKC_FEATURE_ENABLED_MAX);
1651 ret = -EINVAL;
1652 goto exit;
1653 }
1654
1655 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1656 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1657
1658 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1659 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001660 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1661 {
1662 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1663 char extra[32];
1664 tANI_U8 len = 0;
1665
1666 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1667 if (copy_to_user(priv_data.buf, &extra, len + 1))
1668 {
1669 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1670 "%s: failed to copy data to user buffer", __func__);
1671 ret = -EFAULT;
1672 goto exit;
1673 }
1674 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001675#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001676 else {
1677 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
1678 __func__, command);
1679 }
1680
Jeff Johnson295189b2012-06-20 16:38:30 -07001681 }
1682exit:
1683 if (command)
1684 {
1685 kfree(command);
1686 }
1687 return ret;
1688}
1689
Srinivas Girigowdade697412013-02-14 16:31:48 -08001690#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1691void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
1692{
1693 eCsrBand band = -1;
1694 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
1695 switch (band)
1696 {
1697 case eCSR_BAND_ALL:
1698 *pBand = WLAN_HDD_UI_BAND_AUTO;
1699 break;
1700
1701 case eCSR_BAND_24:
1702 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
1703 break;
1704
1705 case eCSR_BAND_5G:
1706 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
1707 break;
1708
1709 default:
1710 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
1711 *pBand = -1;
1712 break;
1713 }
1714}
1715
1716/**---------------------------------------------------------------------------
1717
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001718 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
1719
1720 This function parses the send action frame data passed in the format
1721 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
1722
1723 \param - pValue Pointer to input country code revision
1724 \param - pTargetApBssid Pointer to target Ap bssid
1725 \param - pChannel Pointer to the Target AP channel
1726 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
1727 \param - pBuf Pointer to data
1728 \param - pBufLen Pointer to data length
1729
1730 \return - 0 for success non-zero for failure
1731
1732 --------------------------------------------------------------------------*/
1733VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
1734 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
1735{
1736 tANI_U8 *inPtr = pValue;
1737 tANI_U8 *dataEnd;
1738 int tempInt;
1739 int j = 0;
1740 int i = 0;
1741 int v = 0;
1742 tANI_U8 tempBuf[32];
1743 tANI_U8 tempByte = 0;
1744
1745 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1746 /*no argument after the command*/
1747 if (NULL == inPtr)
1748 {
1749 return -EINVAL;
1750 }
1751
1752 /*no space after the command*/
1753 else if (SPACE_ASCII_VALUE != *inPtr)
1754 {
1755 return -EINVAL;
1756 }
1757
1758 /*removing empty spaces*/
1759 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1760
1761 /*no argument followed by spaces*/
1762 if ('\0' == *inPtr)
1763 {
1764 return -EINVAL;
1765 }
1766
1767 /*getting the first argument ie the target AP bssid */
1768 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
1769 {
1770 return -EINVAL;
1771 }
1772 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
1773 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
1774 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
1775
1776 /* point to the next argument */
1777 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1778 /*no argument after the command*/
1779 if (NULL == inPtr) return -EINVAL;
1780
1781 /*removing empty spaces*/
1782 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1783
1784 /*no argument followed by spaces*/
1785 if ('\0' == *inPtr)
1786 {
1787 return -EINVAL;
1788 }
1789
1790 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07001791 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001792 v = kstrtos32(tempBuf, 10, &tempInt);
1793 if ( v < 0) return -EINVAL;
1794
1795 *pChannel = tempInt;
1796
1797 /* point to the next argument */
1798 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1799 /*no argument after the command*/
1800 if (NULL == inPtr) return -EINVAL;
1801 /*removing empty spaces*/
1802 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1803
1804 /*no argument followed by spaces*/
1805 if ('\0' == *inPtr)
1806 {
1807 return -EINVAL;
1808 }
1809
1810 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07001811 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001812 v = kstrtos32(tempBuf, 10, &tempInt);
1813 if ( v < 0) return -EINVAL;
1814
1815 *pDwellTime = tempInt;
1816
1817 /* point to the next argument */
1818 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1819 /*no argument after the command*/
1820 if (NULL == inPtr) return -EINVAL;
1821 /*removing empty spaces*/
1822 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1823
1824 /*no argument followed by spaces*/
1825 if ('\0' == *inPtr)
1826 {
1827 return -EINVAL;
1828 }
1829
1830 /* find the length of data */
1831 dataEnd = inPtr;
1832 while(('\0' != *dataEnd) )
1833 {
1834 dataEnd++;
1835 ++(*pBufLen);
1836 }
1837 if ( *pBufLen <= 0) return -EINVAL;
1838
1839 *pBuf = vos_mem_malloc(sizeof(*pBufLen));
1840 if (NULL == *pBuf)
1841 {
1842 hddLog(VOS_TRACE_LEVEL_FATAL,
1843 "%s: vos_mem_alloc failed ", __func__);
1844 return -EINVAL;
1845 }
1846
1847 /* the buffer received from the upper layer is character buffer,
1848 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
1849 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
1850 and f0 in 3rd location */
1851 for (i = 0, j = 0; j < *pBufLen; j += 2)
1852 {
1853 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
1854 (*pBuf)[i++] = tempByte;
1855 }
1856 *pBufLen = i;
1857 return VOS_STATUS_SUCCESS;
1858}
1859
1860#endif
1861/**---------------------------------------------------------------------------
1862
Srinivas Girigowdade697412013-02-14 16:31:48 -08001863 \brief hdd_parse_countryrev() - HDD Parse country code revision
1864
1865 This function parses the country code revision passed in the format
1866 SETCOUNTRYREV<space><Country code><space>revision
1867
1868 \param - pValue Pointer to input country code revision
1869 \param - pCountryCode Pointer to local output array to record country code
1870 \param - pRevision Pointer to store revision integer number
1871
1872 \return - 0 for success non-zero for failure
1873
1874 --------------------------------------------------------------------------*/
1875VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
1876{
1877 tANI_U8 *inPtr = pValue;
1878 int tempInt;
1879
1880 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1881 /*no argument after the command*/
1882 if (NULL == inPtr)
1883 {
1884 return -EINVAL;
1885 }
1886
1887 /*no space after the command*/
1888 else if (SPACE_ASCII_VALUE != *inPtr)
1889 {
1890 return -EINVAL;
1891 }
1892
1893 /*removing empty spaces*/
1894 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
1895
1896 /*no argument followed by spaces*/
1897 if ('\0' == *inPtr)
1898 {
1899 return -EINVAL;
1900 }
1901
1902 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07001903 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001904
1905 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1906 "Country code is : %s", pCountryCode);
1907
1908 /*inPtr pointing to the beginning of first space after country code */
1909 inPtr = strpbrk( inPtr, " " );
1910 /*no revision number after the country code argument */
1911 if (NULL == inPtr)
1912 {
1913 return -EINVAL;
1914 }
1915
1916 inPtr++;
1917
1918 /*removing empty space*/
1919 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1920
1921 /*no channel list after the number of channels argument and spaces*/
1922 if (0 == strncmp(pCountryCode, "KR", 2))
1923 {
1924 if ('\0' == *inPtr)
1925 {
1926 return -EINVAL;
1927 }
1928
1929 sscanf(inPtr, "%d", &tempInt);
1930 *pRevision = tempInt;
1931 }
1932 else
1933 {
1934 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1935 "Revision input is required only for Country KR");
1936 return -EINVAL;
1937 }
1938 return VOS_STATUS_SUCCESS;
1939}
1940
1941/**---------------------------------------------------------------------------
1942
1943 \brief hdd_parse_channellist() - HDD Parse channel list
1944
1945 This function parses the channel list passed in the format
1946 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001947 if the Number of channels (N) does not match with the actual number of channels passed
1948 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
1949 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
1950 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
1951 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08001952
1953 \param - pValue Pointer to input channel list
1954 \param - ChannelList Pointer to local output array to record channel list
1955 \param - pNumChannels Pointer to number of roam scan channels
1956
1957 \return - 0 for success non-zero for failure
1958
1959 --------------------------------------------------------------------------*/
1960VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
1961{
1962 tANI_U8 *inPtr = pValue;
1963 int tempInt;
1964 int j = 0;
1965 int v = 0;
1966 char buf[32];
1967
1968 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1969 /*no argument after the command*/
1970 if (NULL == inPtr)
1971 {
1972 return -EINVAL;
1973 }
1974
1975 /*no space after the command*/
1976 else if (SPACE_ASCII_VALUE != *inPtr)
1977 {
1978 return -EINVAL;
1979 }
1980
1981 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001982 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001983
1984 /*no argument followed by spaces*/
1985 if ('\0' == *inPtr)
1986 {
1987 return -EINVAL;
1988 }
1989
1990 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07001991 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001992 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001993 if ((v < 0) ||
1994 (tempInt <= 0) ||
1995 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
1996 {
1997 return -EINVAL;
1998 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001999
2000 *pNumChannels = tempInt;
2001
2002 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2003 "Number of channels are: %d", *pNumChannels);
2004
2005 for (j = 0; j < (*pNumChannels); j++)
2006 {
2007 /*inPtr pointing to the beginning of first space after number of channels*/
2008 inPtr = strpbrk( inPtr, " " );
2009 /*no channel list after the number of channels argument*/
2010 if (NULL == inPtr)
2011 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002012 if (0 != j)
2013 {
2014 *pNumChannels = j;
2015 return VOS_STATUS_SUCCESS;
2016 }
2017 else
2018 {
2019 return -EINVAL;
2020 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002021 }
2022
2023 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002024 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002025
2026 /*no channel list after the number of channels argument and spaces*/
2027 if ( '\0' == *inPtr )
2028 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002029 if (0 != j)
2030 {
2031 *pNumChannels = j;
2032 return VOS_STATUS_SUCCESS;
2033 }
2034 else
2035 {
2036 return -EINVAL;
2037 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002038 }
2039
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002040 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002041 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002042 if ((v < 0) ||
2043 (tempInt <= 0) ||
2044 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2045 {
2046 return -EINVAL;
2047 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002048 pChannelList[j] = tempInt;
2049
2050 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2051 "Channel %d added to preferred channel list",
2052 pChannelList[j] );
2053 }
2054
Srinivas Girigowdade697412013-02-14 16:31:48 -08002055 return VOS_STATUS_SUCCESS;
2056}
2057
Jeff Johnson295189b2012-06-20 16:38:30 -07002058/**---------------------------------------------------------------------------
2059
2060 \brief hdd_open() - HDD Open function
2061
2062 This is called in response to ifconfig up
2063
2064 \param - dev Pointer to net_device structure
2065
2066 \return - 0 for success non-zero for failure
2067
2068 --------------------------------------------------------------------------*/
2069int hdd_open (struct net_device *dev)
2070{
2071 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2072 hdd_context_t *pHddCtx;
2073 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2074 VOS_STATUS status;
2075 v_BOOL_t in_standby = TRUE;
2076
2077 if (NULL == pAdapter)
2078 {
2079 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002080 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002081 return -ENODEV;
2082 }
2083
2084 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2085 if (NULL == pHddCtx)
2086 {
2087 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002088 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002089 return -ENODEV;
2090 }
2091
2092 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2093 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2094 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002095 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2096 {
2097 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302098 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002099 in_standby = FALSE;
2100 break;
2101 }
2102 else
2103 {
2104 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2105 pAdapterNode = pNext;
2106 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002107 }
2108
2109 if (TRUE == in_standby)
2110 {
2111 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2112 {
2113 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2114 "wlan out of power save", __func__);
2115 return -EINVAL;
2116 }
2117 }
2118
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002119 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002120 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2121 {
2122 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002123 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002124 /* Enable TX queues only when we are connected */
2125 netif_tx_start_all_queues(dev);
2126 }
2127
2128 return 0;
2129}
2130
2131int hdd_mon_open (struct net_device *dev)
2132{
2133 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2134
2135 if(pAdapter == NULL) {
2136 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002137 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002138 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002139 }
2140
2141 netif_start_queue(dev);
2142
2143 return 0;
2144}
2145/**---------------------------------------------------------------------------
2146
2147 \brief hdd_stop() - HDD stop function
2148
2149 This is called in response to ifconfig down
2150
2151 \param - dev Pointer to net_device structure
2152
2153 \return - 0 for success non-zero for failure
2154
2155 --------------------------------------------------------------------------*/
2156
2157int hdd_stop (struct net_device *dev)
2158{
2159 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2160 hdd_context_t *pHddCtx;
2161 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2162 VOS_STATUS status;
2163 v_BOOL_t enter_standby = TRUE;
2164
2165 ENTER();
2166
2167 if (NULL == pAdapter)
2168 {
2169 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002170 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002171 return -ENODEV;
2172 }
2173
2174 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2175 if (NULL == pHddCtx)
2176 {
2177 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002178 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002179 return -ENODEV;
2180 }
2181
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002182 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002183 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2184 netif_tx_disable(pAdapter->dev);
2185 netif_carrier_off(pAdapter->dev);
2186
2187
2188 /* SoftAP ifaces should never go in power save mode
2189 making sure same here. */
2190 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2191 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002192 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002193 )
2194 {
2195 /* SoftAP mode, so return from here */
2196 EXIT();
2197 return 0;
2198 }
2199
2200 /* Find if any iface is up then
2201 if any iface is up then can't put device to sleep/ power save mode. */
2202 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2203 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2204 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002205 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2206 {
2207 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302208 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002209 enter_standby = FALSE;
2210 break;
2211 }
2212 else
2213 {
2214 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2215 pAdapterNode = pNext;
2216 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002217 }
2218
2219 if (TRUE == enter_standby)
2220 {
2221 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2222 "entering standby", __func__);
2223 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2224 {
2225 /*log and return success*/
2226 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2227 "wlan in power save", __func__);
2228 }
2229 }
2230
2231 EXIT();
2232 return 0;
2233}
2234
2235/**---------------------------------------------------------------------------
2236
2237 \brief hdd_uninit() - HDD uninit function
2238
2239 This is called during the netdev unregister to uninitialize all data
2240associated with the device
2241
2242 \param - dev Pointer to net_device structure
2243
2244 \return - void
2245
2246 --------------------------------------------------------------------------*/
2247static void hdd_uninit (struct net_device *dev)
2248{
2249 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2250
2251 ENTER();
2252
2253 do
2254 {
2255 if (NULL == pAdapter)
2256 {
2257 hddLog(VOS_TRACE_LEVEL_FATAL,
2258 "%s: NULL pAdapter", __func__);
2259 break;
2260 }
2261
2262 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2263 {
2264 hddLog(VOS_TRACE_LEVEL_FATAL,
2265 "%s: Invalid magic", __func__);
2266 break;
2267 }
2268
2269 if (NULL == pAdapter->pHddCtx)
2270 {
2271 hddLog(VOS_TRACE_LEVEL_FATAL,
2272 "%s: NULL pHddCtx", __func__);
2273 break;
2274 }
2275
2276 if (dev != pAdapter->dev)
2277 {
2278 hddLog(VOS_TRACE_LEVEL_FATAL,
2279 "%s: Invalid device reference", __func__);
2280 /* we haven't validated all cases so let this go for now */
2281 }
2282
2283 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2284
2285 /* after uninit our adapter structure will no longer be valid */
2286 pAdapter->dev = NULL;
2287 pAdapter->magic = 0;
2288 } while (0);
2289
2290 EXIT();
2291}
2292
2293/**---------------------------------------------------------------------------
2294
2295 \brief hdd_release_firmware() -
2296
2297 This function calls the release firmware API to free the firmware buffer.
2298
2299 \param - pFileName Pointer to the File Name.
2300 pCtx - Pointer to the adapter .
2301
2302
2303 \return - 0 for success, non zero for failure
2304
2305 --------------------------------------------------------------------------*/
2306
2307VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2308{
2309 VOS_STATUS status = VOS_STATUS_SUCCESS;
2310 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2311 ENTER();
2312
2313
2314 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2315
2316 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2317
2318 if(pHddCtx->fw) {
2319 release_firmware(pHddCtx->fw);
2320 pHddCtx->fw = NULL;
2321 }
2322 else
2323 status = VOS_STATUS_E_FAILURE;
2324 }
2325 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2326 if(pHddCtx->nv) {
2327 release_firmware(pHddCtx->nv);
2328 pHddCtx->nv = NULL;
2329 }
2330 else
2331 status = VOS_STATUS_E_FAILURE;
2332
2333 }
2334
2335 EXIT();
2336 return status;
2337}
2338
2339/**---------------------------------------------------------------------------
2340
2341 \brief hdd_request_firmware() -
2342
2343 This function reads the firmware file using the request firmware
2344 API and returns the the firmware data and the firmware file size.
2345
2346 \param - pfileName - Pointer to the file name.
2347 - pCtx - Pointer to the adapter .
2348 - ppfw_data - Pointer to the pointer of the firmware data.
2349 - pSize - Pointer to the file size.
2350
2351 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2352
2353 --------------------------------------------------------------------------*/
2354
2355
2356VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2357{
2358 int status;
2359 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2360 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2361 ENTER();
2362
2363 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2364
2365 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2366
2367 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2368 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2369 __func__, pfileName);
2370 retval = VOS_STATUS_E_FAILURE;
2371 }
2372
2373 else {
2374 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2375 *pSize = pHddCtx->fw->size;
2376 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2377 __func__, *pSize);
2378 }
2379 }
2380 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2381
2382 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2383
2384 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2385 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2386 __func__, pfileName);
2387 retval = VOS_STATUS_E_FAILURE;
2388 }
2389
2390 else {
2391 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2392 *pSize = pHddCtx->nv->size;
2393 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2394 __func__, *pSize);
2395 }
2396 }
2397
2398 EXIT();
2399 return retval;
2400}
2401/**---------------------------------------------------------------------------
2402 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2403
2404 This is the function invoked by SME to inform the result of a full power
2405 request issued by HDD
2406
2407 \param - callbackcontext - Pointer to cookie
2408 status - result of request
2409
2410 \return - None
2411
2412--------------------------------------------------------------------------*/
2413void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2414{
2415 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2416
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002417 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002418 if(&pHddCtx->full_pwr_comp_var)
2419 {
2420 complete(&pHddCtx->full_pwr_comp_var);
2421 }
2422}
2423
2424/**---------------------------------------------------------------------------
2425
2426 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2427
2428 This is the function invoked by SME to inform the result of BMPS
2429 request issued by HDD
2430
2431 \param - callbackcontext - Pointer to cookie
2432 status - result of request
2433
2434 \return - None
2435
2436--------------------------------------------------------------------------*/
2437void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2438{
2439
2440 struct completion *completion_var = (struct completion*) callbackContext;
2441
2442 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2443 if(completion_var != NULL)
2444 {
2445 complete(completion_var);
2446 }
2447}
2448
2449/**---------------------------------------------------------------------------
2450
2451 \brief hdd_get_cfg_file_size() -
2452
2453 This function reads the configuration file using the request firmware
2454 API and returns the configuration file size.
2455
2456 \param - pCtx - Pointer to the adapter .
2457 - pFileName - Pointer to the file name.
2458 - pBufSize - Pointer to the buffer size.
2459
2460 \return - 0 for success, non zero for failure
2461
2462 --------------------------------------------------------------------------*/
2463
2464VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2465{
2466 int status;
2467 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2468
2469 ENTER();
2470
2471 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2472
2473 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2474 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2475 status = VOS_STATUS_E_FAILURE;
2476 }
2477 else {
2478 *pBufSize = pHddCtx->fw->size;
2479 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2480 release_firmware(pHddCtx->fw);
2481 pHddCtx->fw = NULL;
2482 }
2483
2484 EXIT();
2485 return VOS_STATUS_SUCCESS;
2486}
2487
2488/**---------------------------------------------------------------------------
2489
2490 \brief hdd_read_cfg_file() -
2491
2492 This function reads the configuration file using the request firmware
2493 API and returns the cfg data and the buffer size of the configuration file.
2494
2495 \param - pCtx - Pointer to the adapter .
2496 - pFileName - Pointer to the file name.
2497 - pBuffer - Pointer to the data buffer.
2498 - pBufSize - Pointer to the buffer size.
2499
2500 \return - 0 for success, non zero for failure
2501
2502 --------------------------------------------------------------------------*/
2503
2504VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2505 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2506{
2507 int status;
2508 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2509
2510 ENTER();
2511
2512 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2513
2514 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2515 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2516 return VOS_STATUS_E_FAILURE;
2517 }
2518 else {
2519 if(*pBufSize != pHddCtx->fw->size) {
2520 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2521 "file size", __func__);
2522 release_firmware(pHddCtx->fw);
2523 pHddCtx->fw = NULL;
2524 return VOS_STATUS_E_FAILURE;
2525 }
2526 else {
2527 if(pBuffer) {
2528 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2529 }
2530 release_firmware(pHddCtx->fw);
2531 pHddCtx->fw = NULL;
2532 }
2533 }
2534
2535 EXIT();
2536
2537 return VOS_STATUS_SUCCESS;
2538}
2539
2540/**---------------------------------------------------------------------------
2541
Jeff Johnson295189b2012-06-20 16:38:30 -07002542 \brief hdd_set_mac_address() -
2543
2544 This function sets the user specified mac address using
2545 the command ifconfig wlanX hw ether <mac adress>.
2546
2547 \param - dev - Pointer to the net device.
2548 - addr - Pointer to the sockaddr.
2549 \return - 0 for success, non zero for failure
2550
2551 --------------------------------------------------------------------------*/
2552
2553static int hdd_set_mac_address(struct net_device *dev, void *addr)
2554{
2555 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2556 struct sockaddr *psta_mac_addr = addr;
2557 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2558
2559 ENTER();
2560
2561 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2562
2563#ifdef HDD_SESSIONIZE
2564 // set the MAC address though the STA ID CFG.
2565 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2566 (v_U8_t *)&pAdapter->macAddressCurrent,
2567 sizeof( pAdapter->macAddressCurrent ),
2568 hdd_set_mac_addr_cb, VOS_FALSE );
2569#endif
2570
2571 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2572
2573 EXIT();
2574 return halStatus;
2575}
2576
2577tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2578{
2579 int i;
2580 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2581 {
2582 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2583 break;
2584 }
2585
2586 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2587 return NULL;
2588
2589 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2590 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2591}
2592
2593void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
2594{
2595 int i;
2596 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2597 {
2598 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
2599 {
2600 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
2601 break;
2602 }
2603 }
2604 return;
2605}
2606
2607#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2608 static struct net_device_ops wlan_drv_ops = {
2609 .ndo_open = hdd_open,
2610 .ndo_stop = hdd_stop,
2611 .ndo_uninit = hdd_uninit,
2612 .ndo_start_xmit = hdd_hard_start_xmit,
2613 .ndo_tx_timeout = hdd_tx_timeout,
2614 .ndo_get_stats = hdd_stats,
2615 .ndo_do_ioctl = hdd_ioctl,
2616 .ndo_set_mac_address = hdd_set_mac_address,
2617 .ndo_select_queue = hdd_select_queue,
2618#ifdef WLAN_FEATURE_PACKET_FILTERING
2619#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
2620 .ndo_set_rx_mode = hdd_set_multicast_list,
2621#else
2622 .ndo_set_multicast_list = hdd_set_multicast_list,
2623#endif //LINUX_VERSION_CODE
2624#endif
2625 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002626 static struct net_device_ops wlan_mon_drv_ops = {
2627 .ndo_open = hdd_mon_open,
2628 .ndo_stop = hdd_stop,
2629 .ndo_uninit = hdd_uninit,
2630 .ndo_start_xmit = hdd_mon_hard_start_xmit,
2631 .ndo_tx_timeout = hdd_tx_timeout,
2632 .ndo_get_stats = hdd_stats,
2633 .ndo_do_ioctl = hdd_ioctl,
2634 .ndo_set_mac_address = hdd_set_mac_address,
2635 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002636
2637#endif
2638
2639void hdd_set_station_ops( struct net_device *pWlanDev )
2640{
2641#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2642 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
2643 pWlanDev->netdev_ops = &wlan_drv_ops;
2644#else
2645 pWlanDev->open = hdd_open;
2646 pWlanDev->stop = hdd_stop;
2647 pWlanDev->uninit = hdd_uninit;
2648 pWlanDev->hard_start_xmit = NULL;
2649 pWlanDev->tx_timeout = hdd_tx_timeout;
2650 pWlanDev->get_stats = hdd_stats;
2651 pWlanDev->do_ioctl = hdd_ioctl;
2652 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
2653 pWlanDev->set_mac_address = hdd_set_mac_address;
2654#endif
2655}
2656
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002657static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07002658{
2659 struct net_device *pWlanDev = NULL;
2660 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002661 /*
2662 * cfg80211 initialization and registration....
2663 */
2664 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
2665
Jeff Johnson295189b2012-06-20 16:38:30 -07002666 if(pWlanDev != NULL)
2667 {
2668
2669 //Save the pointer to the net_device in the HDD adapter
2670 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
2671
Jeff Johnson295189b2012-06-20 16:38:30 -07002672 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
2673
2674 pAdapter->dev = pWlanDev;
2675 pAdapter->pHddCtx = pHddCtx;
2676 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
2677
2678 init_completion(&pAdapter->session_open_comp_var);
2679 init_completion(&pAdapter->session_close_comp_var);
2680 init_completion(&pAdapter->disconnect_comp_var);
2681 init_completion(&pAdapter->linkup_event_var);
2682 init_completion(&pAdapter->cancel_rem_on_chan_var);
2683 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07002684#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2685 init_completion(&pAdapter->offchannel_tx_event);
2686#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002687 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002688#ifdef FEATURE_WLAN_TDLS
2689 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002690 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002691 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002692#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002693 init_completion(&pHddCtx->mc_sus_event_var);
2694 init_completion(&pHddCtx->tx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07002695 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07002696
Jeff Johnson295189b2012-06-20 16:38:30 -07002697 pAdapter->isLinkUpSvcNeeded = FALSE;
2698 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
2699 //Init the net_device structure
2700 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2701
2702 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
2703 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
2704 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
2705 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
2706
2707 hdd_set_station_ops( pAdapter->dev );
2708
2709 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002710 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
2711 pAdapter->wdev.wiphy = pHddCtx->wiphy;
2712 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002713 /* set pWlanDev's parent to underlying device */
2714 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
2715 }
2716
2717 return pAdapter;
2718}
2719
2720VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
2721{
2722 struct net_device *pWlanDev = pAdapter->dev;
2723 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2724 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2725 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2726
2727 if( rtnl_lock_held )
2728 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08002729 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07002730 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
2731 {
2732 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
2733 return VOS_STATUS_E_FAILURE;
2734 }
2735 }
2736 if (register_netdevice(pWlanDev))
2737 {
2738 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
2739 return VOS_STATUS_E_FAILURE;
2740 }
2741 }
2742 else
2743 {
2744 if(register_netdev(pWlanDev))
2745 {
2746 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
2747 return VOS_STATUS_E_FAILURE;
2748 }
2749 }
2750 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
2751
2752 return VOS_STATUS_SUCCESS;
2753}
2754
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002755static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07002756{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002757 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07002758
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002759 if (NULL == pAdapter)
2760 {
2761 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
2762 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07002763 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002764
2765 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2766 {
2767 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
2768 return eHAL_STATUS_NOT_INITIALIZED;
2769 }
2770
2771 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
2772
2773 /* need to make sure all of our scheduled work has completed.
2774 * This callback is called from MC thread context, so it is safe to
2775 * to call below flush workqueue API from here.
2776 */
2777 flush_scheduled_work();
2778
2779 /* We can be blocked while waiting for scheduled work to be
2780 * flushed, and the adapter structure can potentially be freed, in
2781 * which case the magic will have been reset. So make sure the
2782 * magic is still good, and hence the adapter structure is still
2783 * valid, before signaling completion */
2784 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
2785 {
2786 complete(&pAdapter->session_close_comp_var);
2787 }
2788
Jeff Johnson295189b2012-06-20 16:38:30 -07002789 return eHAL_STATUS_SUCCESS;
2790}
2791
2792VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
2793{
2794 struct net_device *pWlanDev = pAdapter->dev;
2795 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2796 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2797 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2798 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2799 int rc = 0;
2800
2801 INIT_COMPLETION(pAdapter->session_open_comp_var);
2802 //Open a SME session for future operation
2803 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
2804 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
2805 if ( !HAL_STATUS_SUCCESS( halStatus ) )
2806 {
2807 hddLog(VOS_TRACE_LEVEL_FATAL,
2808 "sme_OpenSession() failed with status code %08d [x%08lx]",
2809 halStatus, halStatus );
2810 status = VOS_STATUS_E_FAILURE;
2811 goto error_sme_open;
2812 }
2813
2814 //Block on a completion variable. Can't wait forever though.
2815 rc = wait_for_completion_interruptible_timeout(
2816 &pAdapter->session_open_comp_var,
2817 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2818 if (!rc)
2819 {
2820 hddLog(VOS_TRACE_LEVEL_FATAL,
2821 "Session is not opened within timeout period code %08d", rc );
2822 status = VOS_STATUS_E_FAILURE;
2823 goto error_sme_open;
2824 }
2825
2826 // Register wireless extensions
2827 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
2828 {
2829 hddLog(VOS_TRACE_LEVEL_FATAL,
2830 "hdd_register_wext() failed with status code %08d [x%08lx]",
2831 halStatus, halStatus );
2832 status = VOS_STATUS_E_FAILURE;
2833 goto error_register_wext;
2834 }
2835 //Safe to register the hard_start_xmit function again
2836#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2837 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
2838#else
2839 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
2840#endif
2841
2842 //Set the Connection State to Not Connected
2843 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2844
2845 //Set the default operation channel
2846 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
2847
2848 /* Make the default Auth Type as OPEN*/
2849 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2850
2851 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
2852 {
2853 hddLog(VOS_TRACE_LEVEL_FATAL,
2854 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
2855 status, status );
2856 goto error_init_txrx;
2857 }
2858
2859 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2860
2861 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
2862 {
2863 hddLog(VOS_TRACE_LEVEL_FATAL,
2864 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
2865 status, status );
2866 goto error_wmm_init;
2867 }
2868
2869 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2870
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002871#ifdef FEATURE_WLAN_TDLS
2872 if(0 != wlan_hdd_tdls_init(pAdapter))
2873 {
2874 status = VOS_STATUS_E_FAILURE;
2875 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
2876 goto error_tdls_init;
2877 }
2878 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2879#endif
2880
Jeff Johnson295189b2012-06-20 16:38:30 -07002881 return VOS_STATUS_SUCCESS;
2882
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002883#ifdef FEATURE_WLAN_TDLS
2884error_tdls_init:
2885 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2886 hdd_wmm_adapter_close(pAdapter);
2887#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002888error_wmm_init:
2889 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2890 hdd_deinit_tx_rx(pAdapter);
2891error_init_txrx:
2892 hdd_UnregisterWext(pWlanDev);
2893error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002894 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07002895 {
2896 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002897 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002898 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002899 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07002900 {
2901 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002902 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07002903 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002904 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07002905 }
2906}
2907error_sme_open:
2908 return status;
2909}
2910
Jeff Johnson295189b2012-06-20 16:38:30 -07002911void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2912{
2913 hdd_cfg80211_state_t *cfgState;
2914
2915 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
2916
2917 if( NULL != cfgState->buf )
2918 {
2919 int rc;
2920 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
2921 rc = wait_for_completion_interruptible_timeout(
2922 &pAdapter->tx_action_cnf_event,
2923 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2924 if(!rc)
2925 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08002926 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07002927 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
2928 }
2929 }
2930 return;
2931}
Jeff Johnson295189b2012-06-20 16:38:30 -07002932
2933void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2934{
2935 ENTER();
2936 switch ( pAdapter->device_mode )
2937 {
2938 case WLAN_HDD_INFRA_STATION:
2939 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002940 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002941 {
2942 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2943 {
2944 hdd_deinit_tx_rx( pAdapter );
2945 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2946 }
2947
2948 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
2949 {
2950 hdd_wmm_adapter_close( pAdapter );
2951 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2952 }
2953
Jeff Johnson295189b2012-06-20 16:38:30 -07002954 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002955#ifdef FEATURE_WLAN_TDLS
2956 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
2957 {
2958 wlan_hdd_tdls_exit(pAdapter);
2959 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2960 }
2961#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002962
2963 break;
2964 }
2965
2966 case WLAN_HDD_SOFTAP:
2967 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002968 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002969 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002970
2971 hdd_unregister_hostapd(pAdapter);
2972 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07002973 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07002974 break;
2975 }
2976
2977 case WLAN_HDD_MONITOR:
2978 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002979 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07002980 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2981 {
2982 hdd_deinit_tx_rx( pAdapter );
2983 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2984 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002985 if(NULL != pAdapterforTx)
2986 {
2987 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
2988 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002989 break;
2990 }
2991
2992
2993 default:
2994 break;
2995 }
2996
2997 EXIT();
2998}
2999
3000void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3001{
3002 struct net_device *pWlanDev = pAdapter->dev;
3003
3004 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3005 if( rtnl_held )
3006 {
3007 unregister_netdevice(pWlanDev);
3008 }
3009 else
3010 {
3011 unregister_netdev(pWlanDev);
3012 }
3013 // note that the pAdapter is no longer valid at this point
3014 // since the memory has been reclaimed
3015 }
3016
3017}
3018
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003019void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3020{
3021 tSirSetPowerParamsReq powerRequest = { 0 };
3022
3023 powerRequest.uIgnoreDTIM = 1;
3024
3025 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3026 {
3027 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3028 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3029 }
3030 else
3031 {
3032 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3033 }
3034
3035 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3036 *specified during Enter/Exit BMPS when LCD off*/
3037 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3038 NULL, eANI_BOOLEAN_FALSE);
3039 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3040 NULL, eANI_BOOLEAN_FALSE);
3041
3042 /* switch to the DTIM specified in cfg.ini */
3043 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3044 "Switch to DTIM%d", powerRequest.uListenInterval);
3045 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3046
3047}
3048
3049void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3050{
3051 /*Switch back to DTIM 1*/
3052 tSirSetPowerParamsReq powerRequest = { 0 };
3053
3054 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3055 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3056
3057 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3058 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3059 NULL, eANI_BOOLEAN_FALSE);
3060 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3061 NULL, eANI_BOOLEAN_FALSE);
3062
3063 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3064 "Switch to DTIM%d",powerRequest.uListenInterval);
3065 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3066
3067}
3068
Jeff Johnson295189b2012-06-20 16:38:30 -07003069VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3070{
3071 VOS_STATUS status = VOS_STATUS_SUCCESS;
3072
3073 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3074 {
3075 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3076 }
3077
3078 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3079 {
3080 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3081 }
3082
3083 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3084 {
3085 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3086 }
3087
3088 return status;
3089}
3090
3091VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3092{
3093 hdd_adapter_t *pAdapter = NULL;
3094 eHalStatus halStatus;
3095 VOS_STATUS status = VOS_STATUS_E_INVAL;
3096 v_BOOL_t disableBmps = FALSE;
3097 v_BOOL_t disableImps = FALSE;
3098
3099 switch(session_type)
3100 {
3101 case WLAN_HDD_INFRA_STATION:
3102 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003103 case WLAN_HDD_P2P_CLIENT:
3104 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003105 //Exit BMPS -> Is Sta/P2P Client is already connected
3106 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3107 if((NULL != pAdapter)&&
3108 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3109 {
3110 disableBmps = TRUE;
3111 }
3112
3113 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3114 if((NULL != pAdapter)&&
3115 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3116 {
3117 disableBmps = TRUE;
3118 }
3119
3120 //Exit both Bmps and Imps incase of Go/SAP Mode
3121 if((WLAN_HDD_SOFTAP == session_type) ||
3122 (WLAN_HDD_P2P_GO == session_type))
3123 {
3124 disableBmps = TRUE;
3125 disableImps = TRUE;
3126 }
3127
3128 if(TRUE == disableImps)
3129 {
3130 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3131 {
3132 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3133 }
3134 }
3135
3136 if(TRUE == disableBmps)
3137 {
3138 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3139 {
3140 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3141
3142 if(eHAL_STATUS_SUCCESS != halStatus)
3143 {
3144 status = VOS_STATUS_E_FAILURE;
3145 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3146 VOS_ASSERT(0);
3147 return status;
3148 }
3149 }
3150
3151 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3152 {
3153 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3154
3155 if(eHAL_STATUS_SUCCESS != halStatus)
3156 {
3157 status = VOS_STATUS_E_FAILURE;
3158 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3159 VOS_ASSERT(0);
3160 return status;
3161 }
3162 }
3163 }
3164
3165 if((TRUE == disableBmps) ||
3166 (TRUE == disableImps))
3167 {
3168 /* Now, get the chip into Full Power now */
3169 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3170 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3171 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3172
3173 if(halStatus != eHAL_STATUS_SUCCESS)
3174 {
3175 if(halStatus == eHAL_STATUS_PMC_PENDING)
3176 {
3177 //Block on a completion variable. Can't wait forever though
3178 wait_for_completion_interruptible_timeout(
3179 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3180 }
3181 else
3182 {
3183 status = VOS_STATUS_E_FAILURE;
3184 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3185 VOS_ASSERT(0);
3186 return status;
3187 }
3188 }
3189
3190 status = VOS_STATUS_SUCCESS;
3191 }
3192
3193 break;
3194 }
3195 return status;
3196}
3197
3198hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003199 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003200 tANI_U8 rtnl_held )
3201{
3202 hdd_adapter_t *pAdapter = NULL;
3203 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3204 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3205 VOS_STATUS exitbmpsStatus;
3206
3207 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3208
3209 //Disable BMPS incase of Concurrency
3210 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3211
3212 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3213 {
3214 //Fail to Exit BMPS
3215 VOS_ASSERT(0);
3216 return NULL;
3217 }
3218
3219 switch(session_type)
3220 {
3221 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003222 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003223 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003224 {
3225 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3226
3227 if( NULL == pAdapter )
3228 return NULL;
3229
Jeff Johnsone7245742012-09-05 17:12:55 -07003230 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3231 NL80211_IFTYPE_P2P_CLIENT:
3232 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003233
Jeff Johnson295189b2012-06-20 16:38:30 -07003234 pAdapter->device_mode = session_type;
3235
3236 status = hdd_init_station_mode( pAdapter );
3237 if( VOS_STATUS_SUCCESS != status )
3238 goto err_free_netdev;
3239
3240 status = hdd_register_interface( pAdapter, rtnl_held );
3241 if( VOS_STATUS_SUCCESS != status )
3242 {
3243 hdd_deinit_adapter(pHddCtx, pAdapter);
3244 goto err_free_netdev;
3245 }
3246 //Stop the Interface TX queue.
3247 netif_tx_disable(pAdapter->dev);
3248 //netif_tx_disable(pWlanDev);
3249 netif_carrier_off(pAdapter->dev);
3250
3251 break;
3252 }
3253
Jeff Johnson295189b2012-06-20 16:38:30 -07003254 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003255 case WLAN_HDD_SOFTAP:
3256 {
3257 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3258 if( NULL == pAdapter )
3259 return NULL;
3260
Jeff Johnson295189b2012-06-20 16:38:30 -07003261 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3262 NL80211_IFTYPE_AP:
3263 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003264 pAdapter->device_mode = session_type;
3265
3266 status = hdd_init_ap_mode(pAdapter);
3267 if( VOS_STATUS_SUCCESS != status )
3268 goto err_free_netdev;
3269
3270 status = hdd_register_hostapd( pAdapter, rtnl_held );
3271 if( VOS_STATUS_SUCCESS != status )
3272 {
3273 hdd_deinit_adapter(pHddCtx, pAdapter);
3274 goto err_free_netdev;
3275 }
3276
3277 netif_tx_disable(pAdapter->dev);
3278 netif_carrier_off(pAdapter->dev);
3279
3280 hdd_set_conparam( 1 );
3281 break;
3282 }
3283 case WLAN_HDD_MONITOR:
3284 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003285 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3286 if( NULL == pAdapter )
3287 return NULL;
3288
3289 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3290 pAdapter->device_mode = session_type;
3291 status = hdd_register_interface( pAdapter, rtnl_held );
3292#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3293 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3294#else
3295 pAdapter->dev->open = hdd_mon_open;
3296 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3297#endif
3298 hdd_init_tx_rx( pAdapter );
3299 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3300 //Set adapter to be used for data tx. It will use either GO or softap.
3301 pAdapter->sessionCtx.monitor.pAdapterForTx =
3302 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003303 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3304 {
3305 pAdapter->sessionCtx.monitor.pAdapterForTx =
3306 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3307 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003308 /* This workqueue will be used to transmit management packet over
3309 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003310 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3311 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3312 return NULL;
3313 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003314
Jeff Johnson295189b2012-06-20 16:38:30 -07003315 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3316 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003317 }
3318 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003319 case WLAN_HDD_FTM:
3320 {
3321 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3322
3323 if( NULL == pAdapter )
3324 return NULL;
3325 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3326 * message while loading driver in FTM mode. */
3327 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3328 pAdapter->device_mode = session_type;
3329 status = hdd_register_interface( pAdapter, rtnl_held );
3330 }
3331 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003332 default:
3333 {
3334 VOS_ASSERT(0);
3335 return NULL;
3336 }
3337 }
3338
3339
3340 if( VOS_STATUS_SUCCESS == status )
3341 {
3342 //Add it to the hdd's session list.
3343 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3344 if( NULL == pHddAdapterNode )
3345 {
3346 status = VOS_STATUS_E_NOMEM;
3347 }
3348 else
3349 {
3350 pHddAdapterNode->pAdapter = pAdapter;
3351 status = hdd_add_adapter_back ( pHddCtx,
3352 pHddAdapterNode );
3353 }
3354 }
3355
3356 if( VOS_STATUS_SUCCESS != status )
3357 {
3358 if( NULL != pAdapter )
3359 {
3360 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3361 pAdapter = NULL;
3362 }
3363 if( NULL != pHddAdapterNode )
3364 {
3365 vos_mem_free( pHddAdapterNode );
3366 }
3367
3368 goto resume_bmps;
3369 }
3370
3371 if(VOS_STATUS_SUCCESS == status)
3372 {
3373 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3374
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003375 //Initialize the WoWL service
3376 if(!hdd_init_wowl(pAdapter))
3377 {
3378 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3379 goto err_free_netdev;
3380 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003381 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003382 return pAdapter;
3383
3384err_free_netdev:
3385 free_netdev(pAdapter->dev);
3386 wlan_hdd_release_intf_addr( pHddCtx,
3387 pAdapter->macAddressCurrent.bytes );
3388
3389resume_bmps:
3390 //If bmps disabled enable it
3391 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3392 {
3393 hdd_enable_bmps_imps(pHddCtx);
3394 }
3395 return NULL;
3396}
3397
3398VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3399 tANI_U8 rtnl_held )
3400{
3401 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3402 VOS_STATUS status;
3403
3404 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3405 if( VOS_STATUS_SUCCESS != status )
3406 return status;
3407
3408 while ( pCurrent->pAdapter != pAdapter )
3409 {
3410 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3411 if( VOS_STATUS_SUCCESS != status )
3412 break;
3413
3414 pCurrent = pNext;
3415 }
3416 pAdapterNode = pCurrent;
3417 if( VOS_STATUS_SUCCESS == status )
3418 {
3419 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3420 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3421 hdd_remove_adapter( pHddCtx, pAdapterNode );
3422 vos_mem_free( pAdapterNode );
3423
Jeff Johnson295189b2012-06-20 16:38:30 -07003424
3425 /* If there is a single session of STA/P2P client, re-enable BMPS */
3426 if ((!vos_concurrent_sessions_running()) &&
3427 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3428 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3429 {
3430 hdd_enable_bmps_imps(pHddCtx);
3431 }
3432
3433 return VOS_STATUS_SUCCESS;
3434 }
3435
3436 return VOS_STATUS_E_FAILURE;
3437}
3438
3439VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3440{
3441 hdd_adapter_list_node_t *pHddAdapterNode;
3442 VOS_STATUS status;
3443
3444 ENTER();
3445
3446 do
3447 {
3448 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3449 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3450 {
3451 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3452 vos_mem_free( pHddAdapterNode );
3453 }
3454 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3455
3456 EXIT();
3457
3458 return VOS_STATUS_SUCCESS;
3459}
3460
3461void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3462{
3463 v_U8_t addIE[1] = {0};
3464
3465 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3466 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3467 eANI_BOOLEAN_FALSE) )
3468 {
3469 hddLog(LOGE,
3470 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3471 }
3472
3473 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3474 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3475 eANI_BOOLEAN_FALSE) )
3476 {
3477 hddLog(LOGE,
3478 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3479 }
3480
3481 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3482 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3483 eANI_BOOLEAN_FALSE) )
3484 {
3485 hddLog(LOGE,
3486 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3487 }
3488}
3489
3490VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3491{
3492 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3493 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3494 union iwreq_data wrqu;
3495
3496 ENTER();
3497
3498 switch(pAdapter->device_mode)
3499 {
3500 case WLAN_HDD_INFRA_STATION:
3501 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003502 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003503 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3504 {
3505 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3506 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3507 pAdapter->sessionId,
3508 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3509 else
3510 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3511 pAdapter->sessionId,
3512 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3513 //success implies disconnect command got queued up successfully
3514 if(halStatus == eHAL_STATUS_SUCCESS)
3515 {
3516 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3517 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3518 }
3519 memset(&wrqu, '\0', sizeof(wrqu));
3520 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3521 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3522 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3523 }
3524 else
3525 {
3526 hdd_abort_mac_scan(pHddCtx);
3527 }
3528
3529 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3530 {
3531 INIT_COMPLETION(pAdapter->session_close_comp_var);
3532 if (eHAL_STATUS_SUCCESS ==
3533 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3534 hdd_smeCloseSessionCallback, pAdapter))
3535 {
3536 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003537 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003538 &pAdapter->session_close_comp_var,
3539 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3540 }
3541 }
3542
3543 break;
3544
3545 case WLAN_HDD_SOFTAP:
3546 case WLAN_HDD_P2P_GO:
3547 //Any softap specific cleanup here...
3548 mutex_lock(&pHddCtx->sap_lock);
3549 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3550 {
3551 VOS_STATUS status;
3552 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3553
3554 //Stop Bss.
3555 status = WLANSAP_StopBss(pHddCtx->pvosContext);
3556 if (VOS_IS_STATUS_SUCCESS(status))
3557 {
3558 hdd_hostapd_state_t *pHostapdState =
3559 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3560
3561 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
3562
3563 if (!VOS_IS_STATUS_SUCCESS(status))
3564 {
3565 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003566 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003567 }
3568 }
3569 else
3570 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003571 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003572 }
3573 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
3574
3575 if (eHAL_STATUS_FAILURE ==
3576 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
3577 0, NULL, eANI_BOOLEAN_FALSE))
3578 {
3579 hddLog(LOGE,
3580 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003581 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003582 }
3583
3584 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
3585 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
3586 eANI_BOOLEAN_FALSE) )
3587 {
3588 hddLog(LOGE,
3589 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
3590 }
3591
3592 // Reset WNI_CFG_PROBE_RSP Flags
3593 wlan_hdd_reset_prob_rspies(pAdapter);
3594 kfree(pAdapter->sessionCtx.ap.beacon);
3595 pAdapter->sessionCtx.ap.beacon = NULL;
3596 }
3597 mutex_unlock(&pHddCtx->sap_lock);
3598 break;
3599 case WLAN_HDD_MONITOR:
3600 break;
3601 default:
3602 break;
3603 }
3604
3605 EXIT();
3606 return VOS_STATUS_SUCCESS;
3607}
3608
3609VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
3610{
3611 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3612 VOS_STATUS status;
3613 hdd_adapter_t *pAdapter;
3614
3615 ENTER();
3616
3617 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3618
3619 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3620 {
3621 pAdapter = pAdapterNode->pAdapter;
3622 netif_tx_disable(pAdapter->dev);
3623 netif_carrier_off(pAdapter->dev);
3624
3625 hdd_stop_adapter( pHddCtx, pAdapter );
3626
3627 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3628 pAdapterNode = pNext;
3629 }
3630
3631 EXIT();
3632
3633 return VOS_STATUS_SUCCESS;
3634}
3635
3636VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
3637{
3638 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3639 VOS_STATUS status;
3640 hdd_adapter_t *pAdapter;
3641
3642 ENTER();
3643
3644 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3645
3646 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3647 {
3648 pAdapter = pAdapterNode->pAdapter;
3649 netif_tx_disable(pAdapter->dev);
3650 netif_carrier_off(pAdapter->dev);
3651
3652 //Record whether STA is associated
3653 pAdapter->sessionCtx.station.bSendDisconnect =
3654 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
3655 VOS_TRUE : VOS_FALSE;
3656
3657 hdd_deinit_tx_rx(pAdapter);
3658 hdd_wmm_adapter_close(pAdapter);
3659
3660 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3661 pAdapterNode = pNext;
3662 }
3663
3664 EXIT();
3665
3666 return VOS_STATUS_SUCCESS;
3667}
3668
3669VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
3670{
3671 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3672 VOS_STATUS status;
3673 hdd_adapter_t *pAdapter;
3674 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
3675
3676 ENTER();
3677
3678 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3679
3680 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3681 {
3682 pAdapter = pAdapterNode->pAdapter;
3683
3684 switch(pAdapter->device_mode)
3685 {
3686 case WLAN_HDD_INFRA_STATION:
3687 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003688 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003689 hdd_init_station_mode(pAdapter);
3690 /* Open the gates for HDD to receive Wext commands */
3691 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003692 pHddCtx->scan_info.mScanPending = FALSE;
3693 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003694
3695 //Trigger the initial scan
3696 hdd_wlan_initial_scan(pAdapter);
3697
3698 //Indicate disconnect event to supplicant if associated previously
3699 if(pAdapter->sessionCtx.station.bSendDisconnect)
3700 {
3701 union iwreq_data wrqu;
3702 memset(&wrqu, '\0', sizeof(wrqu));
3703 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3704 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3705 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3706 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
3707
Jeff Johnson295189b2012-06-20 16:38:30 -07003708 /* indicate disconnected event to nl80211 */
3709 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
3710 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003711 }
3712 break;
3713
3714 case WLAN_HDD_SOFTAP:
3715 /* softAP can handle SSR */
3716 break;
3717
3718 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003719 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
3720 __func__);
3721 /* event supplicant to restart */
3722 cfg80211_del_sta(pAdapter->dev,
3723 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003724 break;
3725
3726 case WLAN_HDD_MONITOR:
3727 /* monitor interface start */
3728 break;
3729 default:
3730 break;
3731 }
3732
3733 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3734 pAdapterNode = pNext;
3735 }
3736
3737 EXIT();
3738
3739 return VOS_STATUS_SUCCESS;
3740}
3741
3742VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
3743{
3744 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3745 hdd_adapter_t *pAdapter;
3746 VOS_STATUS status;
3747 v_U32_t roamId;
3748
3749 ENTER();
3750
3751 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3752
3753 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3754 {
3755 pAdapter = pAdapterNode->pAdapter;
3756
3757 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3758 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
3759 {
3760 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3761 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3762
3763 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3764 init_completion(&pAdapter->disconnect_comp_var);
3765 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
3766 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3767
3768 wait_for_completion_interruptible_timeout(
3769 &pAdapter->disconnect_comp_var,
3770 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3771
3772 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
3773 pHddCtx->isAmpAllowed = VOS_FALSE;
3774 sme_RoamConnect(pHddCtx->hHal,
3775 pAdapter->sessionId, &(pWextState->roamProfile),
3776 &roamId);
3777 }
3778
3779 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3780 pAdapterNode = pNext;
3781 }
3782
3783 EXIT();
3784
3785 return VOS_STATUS_SUCCESS;
3786}
3787
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07003788void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
3789{
3790 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3791 VOS_STATUS status;
3792 hdd_adapter_t *pAdapter;
3793 hdd_station_ctx_t *pHddStaCtx;
3794 hdd_ap_ctx_t *pHddApCtx;
3795 hdd_hostapd_state_t * pHostapdState;
3796 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
3797 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
3798 const char *p2pMode = "DEV";
3799 const char *ccMode = "Standalone";
3800 int n;
3801
3802 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3803 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3804 {
3805 pAdapter = pAdapterNode->pAdapter;
3806 switch (pAdapter->device_mode) {
3807 case WLAN_HDD_INFRA_STATION:
3808 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3809 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3810 staChannel = pHddStaCtx->conn_info.operationChannel;
3811 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
3812 }
3813 break;
3814 case WLAN_HDD_P2P_CLIENT:
3815 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3816 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3817 p2pChannel = pHddStaCtx->conn_info.operationChannel;
3818 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
3819 p2pMode = "CLI";
3820 }
3821 break;
3822 case WLAN_HDD_P2P_GO:
3823 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3824 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3825 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3826 p2pChannel = pHddApCtx->operatingChannel;
3827 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
3828 }
3829 p2pMode = "GO";
3830 break;
3831 case WLAN_HDD_SOFTAP:
3832 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3833 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3834 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3835 apChannel = pHddApCtx->operatingChannel;
3836 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
3837 }
3838 break;
3839 default:
3840 break;
3841 }
3842 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3843 pAdapterNode = pNext;
3844 }
3845 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
3846 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
3847 }
3848 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
3849 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
3850 if (p2pChannel > 0) {
3851 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
3852 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
3853 }
3854 if (apChannel > 0) {
3855 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
3856 apChannel, MAC_ADDR_ARRAY(apBssid));
3857 }
3858
3859 if (p2pChannel > 0 && apChannel > 0) {
3860 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
3861 }
3862}
3863
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003864bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07003865{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003866 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07003867}
3868
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003869/* Once SSR is disabled then it cannot be set. */
3870void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07003871{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003872 if (HDD_SSR_DISABLED == isSsrRequired)
3873 return;
3874
Jeff Johnson295189b2012-06-20 16:38:30 -07003875 isSsrRequired = value;
3876}
3877
3878VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
3879 hdd_adapter_list_node_t** ppAdapterNode)
3880{
3881 VOS_STATUS status;
3882 spin_lock(&pHddCtx->hddAdapters.lock);
3883 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
3884 (hdd_list_node_t**) ppAdapterNode );
3885 spin_unlock(&pHddCtx->hddAdapters.lock);
3886 return status;
3887}
3888
3889VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
3890 hdd_adapter_list_node_t* pAdapterNode,
3891 hdd_adapter_list_node_t** pNextAdapterNode)
3892{
3893 VOS_STATUS status;
3894 spin_lock(&pHddCtx->hddAdapters.lock);
3895 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
3896 (hdd_list_node_t*) pAdapterNode,
3897 (hdd_list_node_t**)pNextAdapterNode );
3898
3899 spin_unlock(&pHddCtx->hddAdapters.lock);
3900 return status;
3901}
3902
3903VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
3904 hdd_adapter_list_node_t* pAdapterNode)
3905{
3906 VOS_STATUS status;
3907 spin_lock(&pHddCtx->hddAdapters.lock);
3908 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
3909 &pAdapterNode->node );
3910 spin_unlock(&pHddCtx->hddAdapters.lock);
3911 return status;
3912}
3913
3914VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
3915 hdd_adapter_list_node_t** ppAdapterNode)
3916{
3917 VOS_STATUS status;
3918 spin_lock(&pHddCtx->hddAdapters.lock);
3919 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
3920 (hdd_list_node_t**) ppAdapterNode );
3921 spin_unlock(&pHddCtx->hddAdapters.lock);
3922 return status;
3923}
3924
3925VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
3926 hdd_adapter_list_node_t* pAdapterNode)
3927{
3928 VOS_STATUS status;
3929 spin_lock(&pHddCtx->hddAdapters.lock);
3930 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
3931 (hdd_list_node_t*) pAdapterNode );
3932 spin_unlock(&pHddCtx->hddAdapters.lock);
3933 return status;
3934}
3935
3936VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
3937 hdd_adapter_list_node_t* pAdapterNode)
3938{
3939 VOS_STATUS status;
3940 spin_lock(&pHddCtx->hddAdapters.lock);
3941 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
3942 (hdd_list_node_t*) pAdapterNode );
3943 spin_unlock(&pHddCtx->hddAdapters.lock);
3944 return status;
3945}
3946
3947hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
3948 tSirMacAddr macAddr )
3949{
3950 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3951 hdd_adapter_t *pAdapter;
3952 VOS_STATUS status;
3953
3954 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3955
3956 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3957 {
3958 pAdapter = pAdapterNode->pAdapter;
3959
3960 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
3961 macAddr, sizeof(tSirMacAddr) ) )
3962 {
3963 return pAdapter;
3964 }
3965 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3966 pAdapterNode = pNext;
3967 }
3968
3969 return NULL;
3970
3971}
3972
3973hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
3974{
3975 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3976 hdd_adapter_t *pAdapter;
3977 VOS_STATUS status;
3978
3979 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3980
3981 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3982 {
3983 pAdapter = pAdapterNode->pAdapter;
3984
3985 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
3986 IFNAMSIZ ) )
3987 {
3988 return pAdapter;
3989 }
3990 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3991 pAdapterNode = pNext;
3992 }
3993
3994 return NULL;
3995
3996}
3997
3998hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
3999{
4000 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4001 hdd_adapter_t *pAdapter;
4002 VOS_STATUS status;
4003
4004 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4005
4006 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4007 {
4008 pAdapter = pAdapterNode->pAdapter;
4009
4010 if( pAdapter && (mode == pAdapter->device_mode) )
4011 {
4012 return pAdapter;
4013 }
4014 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4015 pAdapterNode = pNext;
4016 }
4017
4018 return NULL;
4019
4020}
4021
4022//Remove this function later
4023hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4024{
4025 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4026 hdd_adapter_t *pAdapter;
4027 VOS_STATUS status;
4028
4029 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4030
4031 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4032 {
4033 pAdapter = pAdapterNode->pAdapter;
4034
4035 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4036 {
4037 return pAdapter;
4038 }
4039
4040 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4041 pAdapterNode = pNext;
4042 }
4043
4044 return NULL;
4045
4046}
4047
Jeff Johnson295189b2012-06-20 16:38:30 -07004048/**---------------------------------------------------------------------------
4049
4050 \brief hdd_set_monitor_tx_adapter() -
4051
4052 This API initializes the adapter to be used while transmitting on monitor
4053 adapter.
4054
4055 \param - pHddCtx - Pointer to the HDD context.
4056 pAdapter - Adapter that will used for TX. This can be NULL.
4057 \return - None.
4058 --------------------------------------------------------------------------*/
4059void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4060{
4061 hdd_adapter_t *pMonAdapter;
4062
4063 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4064
4065 if( NULL != pMonAdapter )
4066 {
4067 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4068 }
4069}
Jeff Johnson295189b2012-06-20 16:38:30 -07004070/**---------------------------------------------------------------------------
4071
4072 \brief hdd_select_queue() -
4073
4074 This API returns the operating channel of the requested device mode
4075
4076 \param - pHddCtx - Pointer to the HDD context.
4077 - mode - Device mode for which operating channel is required
4078 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4079 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4080 \return - channel number. "0" id the requested device is not found OR it is not connected.
4081 --------------------------------------------------------------------------*/
4082v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4083{
4084 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4085 VOS_STATUS status;
4086 hdd_adapter_t *pAdapter;
4087 v_U8_t operatingChannel = 0;
4088
4089 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4090
4091 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4092 {
4093 pAdapter = pAdapterNode->pAdapter;
4094
4095 if( mode == pAdapter->device_mode )
4096 {
4097 switch(pAdapter->device_mode)
4098 {
4099 case WLAN_HDD_INFRA_STATION:
4100 case WLAN_HDD_P2P_CLIENT:
4101 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4102 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4103 break;
4104 case WLAN_HDD_SOFTAP:
4105 case WLAN_HDD_P2P_GO:
4106 /*softap connection info */
4107 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4108 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4109 break;
4110 default:
4111 break;
4112 }
4113
4114 break; //Found the device of interest. break the loop
4115 }
4116
4117 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4118 pAdapterNode = pNext;
4119 }
4120 return operatingChannel;
4121}
4122
4123#ifdef WLAN_FEATURE_PACKET_FILTERING
4124/**---------------------------------------------------------------------------
4125
4126 \brief hdd_set_multicast_list() -
4127
4128 This used to set the multicast address list.
4129
4130 \param - dev - Pointer to the WLAN device.
4131 - skb - Pointer to OS packet (sk_buff).
4132 \return - success/fail
4133
4134 --------------------------------------------------------------------------*/
4135static void hdd_set_multicast_list(struct net_device *dev)
4136{
4137 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004138 int mc_count;
4139 int i = 0;
4140 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304141
4142 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004143 {
4144 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304145 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004146 return;
4147 }
4148
4149 if (dev->flags & IFF_ALLMULTI)
4150 {
4151 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004152 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304153 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004154 }
4155 else
4156 {
4157 mc_count = netdev_mc_count(dev);
4158 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004159 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004160 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4161 {
4162 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004163 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304164 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004165 return;
4166 }
4167
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304168 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004169
4170 netdev_for_each_mc_addr(ha, dev) {
4171 if (i == mc_count)
4172 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304173 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4174 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4175 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004176 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304177 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004178 i++;
4179 }
4180 }
4181 return;
4182}
4183#endif
4184
4185/**---------------------------------------------------------------------------
4186
4187 \brief hdd_select_queue() -
4188
4189 This function is registered with the Linux OS for network
4190 core to decide which queue to use first.
4191
4192 \param - dev - Pointer to the WLAN device.
4193 - skb - Pointer to OS packet (sk_buff).
4194 \return - ac, Queue Index/access category corresponding to UP in IP header
4195
4196 --------------------------------------------------------------------------*/
4197v_U16_t hdd_select_queue(struct net_device *dev,
4198 struct sk_buff *skb)
4199{
4200 return hdd_wmm_select_queue(dev, skb);
4201}
4202
4203
4204/**---------------------------------------------------------------------------
4205
4206 \brief hdd_wlan_initial_scan() -
4207
4208 This function triggers the initial scan
4209
4210 \param - pAdapter - Pointer to the HDD adapter.
4211
4212 --------------------------------------------------------------------------*/
4213void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4214{
4215 tCsrScanRequest scanReq;
4216 tCsrChannelInfo channelInfo;
4217 eHalStatus halStatus;
4218 unsigned long scanId;
4219 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4220
4221 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4222 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4223 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4224
4225 if(sme_Is11dSupported(pHddCtx->hHal))
4226 {
4227 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4228 if ( HAL_STATUS_SUCCESS( halStatus ) )
4229 {
4230 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4231 if( !scanReq.ChannelInfo.ChannelList )
4232 {
4233 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4234 vos_mem_free(channelInfo.ChannelList);
4235 return;
4236 }
4237 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4238 channelInfo.numOfChannels);
4239 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4240 vos_mem_free(channelInfo.ChannelList);
4241 }
4242
4243 scanReq.scanType = eSIR_PASSIVE_SCAN;
4244 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4245 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4246 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4247 }
4248 else
4249 {
4250 scanReq.scanType = eSIR_ACTIVE_SCAN;
4251 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4252 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4253 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4254 }
4255
4256 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4257 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4258 {
4259 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4260 __func__, halStatus );
4261 }
4262
4263 if(sme_Is11dSupported(pHddCtx->hHal))
4264 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4265}
4266
4267struct fullPowerContext
4268{
4269 struct completion completion;
4270 unsigned int magic;
4271};
4272#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4273
4274/**---------------------------------------------------------------------------
4275
4276 \brief hdd_full_power_callback() - HDD full power callback function
4277
4278 This is the function invoked by SME to inform the result of a full power
4279 request issued by HDD
4280
4281 \param - callbackcontext - Pointer to cookie
4282 \param - status - result of request
4283
4284 \return - None
4285
4286 --------------------------------------------------------------------------*/
4287static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4288{
4289 struct fullPowerContext *pContext = callbackContext;
4290
4291 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304292 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004293
4294 if (NULL == callbackContext)
4295 {
4296 hddLog(VOS_TRACE_LEVEL_ERROR,
4297 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004298 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004299 return;
4300 }
4301
4302 /* there is a race condition that exists between this callback function
4303 and the caller since the caller could time out either before or
4304 while this code is executing. we'll assume the timeout hasn't
4305 occurred, but we'll verify that right before we save our work */
4306
4307 if (POWER_CONTEXT_MAGIC != pContext->magic)
4308 {
4309 /* the caller presumably timed out so there is nothing we can do */
4310 hddLog(VOS_TRACE_LEVEL_WARN,
4311 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004312 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004313 return;
4314 }
4315
4316 /* the race is on. caller could have timed out immediately after
4317 we verified the magic, but if so, caller will wait a short time
4318 for us to notify the caller, so the context will stay valid */
4319 complete(&pContext->completion);
4320}
4321
4322/**---------------------------------------------------------------------------
4323
4324 \brief hdd_wlan_exit() - HDD WLAN exit function
4325
4326 This is the driver exit point (invoked during rmmod)
4327
4328 \param - pHddCtx - Pointer to the HDD Context
4329
4330 \return - None
4331
4332 --------------------------------------------------------------------------*/
4333void hdd_wlan_exit(hdd_context_t *pHddCtx)
4334{
4335 eHalStatus halStatus;
4336 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4337 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304338 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004339 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004340 struct fullPowerContext powerContext;
4341 long lrc;
4342
4343 ENTER();
4344
Jeff Johnson88ba7742013-02-27 14:36:02 -08004345 if (VOS_FTM_MODE != hdd_get_conparam())
4346 {
4347 // Unloading, restart logic is no more required.
4348 wlan_hdd_restart_deinit(pHddCtx);
4349 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004350
Jeff Johnson295189b2012-06-20 16:38:30 -07004351 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004352 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004353 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004354 {
4355 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4356 WLAN_HDD_INFRA_STATION);
4357 if (pAdapter == NULL)
4358 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4359
4360 if (pAdapter != NULL)
4361 {
4362 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4363 hdd_UnregisterWext(pAdapter->dev);
4364 }
4365 }
4366 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004367
Jeff Johnson295189b2012-06-20 16:38:30 -07004368 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004369 {
4370 wlan_hdd_ftm_close(pHddCtx);
4371 goto free_hdd_ctx;
4372 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004373 //Stop the Interface TX queue.
4374 //netif_tx_disable(pWlanDev);
4375 //netif_carrier_off(pWlanDev);
4376
Jeff Johnson295189b2012-06-20 16:38:30 -07004377 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4378 {
4379 pAdapter = hdd_get_adapter(pHddCtx,
4380 WLAN_HDD_SOFTAP);
4381 }
4382 else
4383 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004384 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004385 {
4386 pAdapter = hdd_get_adapter(pHddCtx,
4387 WLAN_HDD_INFRA_STATION);
4388 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004389 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004390 /* DeRegister with platform driver as client for Suspend/Resume */
4391 vosStatus = hddDeregisterPmOps(pHddCtx);
4392 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4393 {
4394 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4395 VOS_ASSERT(0);
4396 }
4397
4398 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4399 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4400 {
4401 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4402 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004403
4404 // Cancel any outstanding scan requests. We are about to close all
4405 // of our adapters, but an adapter structure is what SME passes back
4406 // to our callback function. Hence if there are any outstanding scan
4407 // requests then there is a race condition between when the adapter
4408 // is closed and when the callback is invoked. We try to resolve that
4409 // race condition here by canceling any outstanding scans before we
4410 // close the adapters.
4411 // Note that the scans may be cancelled in an asynchronous manner, so
4412 // ideally there needs to be some kind of synchronization. Rather than
4413 // introduce a new synchronization here, we will utilize the fact that
4414 // we are about to Request Full Power, and since that is synchronized,
4415 // the expectation is that by the time Request Full Power has completed,
4416 // all scans will be cancelled.
4417 hdd_abort_mac_scan( pHddCtx );
4418
4419 //Disable IMPS/BMPS as we do not want the device to enter any power
4420 //save mode during shutdown
4421 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4422 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4423 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4424
4425 //Ensure that device is in full power as we will touch H/W during vos_Stop
4426 init_completion(&powerContext.completion);
4427 powerContext.magic = POWER_CONTEXT_MAGIC;
4428
4429 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4430 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4431
4432 if (eHAL_STATUS_SUCCESS != halStatus)
4433 {
4434 if (eHAL_STATUS_PMC_PENDING == halStatus)
4435 {
4436 /* request was sent -- wait for the response */
4437 lrc = wait_for_completion_interruptible_timeout(
4438 &powerContext.completion,
4439 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4440 /* either we have a response or we timed out
4441 either way, first invalidate our magic */
4442 powerContext.magic = 0;
4443 if (lrc <= 0)
4444 {
4445 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004446 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004447 /* there is a race condition such that the callback
4448 function could be executing at the same time we are. of
4449 primary concern is if the callback function had already
4450 verified the "magic" but hasn't yet set the completion
4451 variable. Since the completion variable is on our
4452 stack, we'll delay just a bit to make sure the data is
4453 still valid if that is the case */
4454 msleep(50);
4455 }
4456 }
4457 else
4458 {
4459 hddLog(VOS_TRACE_LEVEL_ERROR,
4460 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004461 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004462 VOS_ASSERT(0);
4463 /* continue -- need to clean up as much as possible */
4464 }
4465 }
4466
4467 // Unregister the Net Device Notifier
4468 unregister_netdevice_notifier(&hdd_netdev_notifier);
4469
Jeff Johnson295189b2012-06-20 16:38:30 -07004470 hdd_stop_all_adapters( pHddCtx );
4471
Jeff Johnson295189b2012-06-20 16:38:30 -07004472#ifdef WLAN_BTAMP_FEATURE
4473 vosStatus = WLANBAP_Stop(pVosContext);
4474 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4475 {
4476 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4477 "%s: Failed to stop BAP",__func__);
4478 }
4479#endif //WLAN_BTAMP_FEATURE
4480
4481 //Stop all the modules
4482 vosStatus = vos_stop( pVosContext );
4483 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4484 {
4485 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4486 "%s: Failed to stop VOSS",__func__);
4487 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4488 }
4489
Jeff Johnson295189b2012-06-20 16:38:30 -07004490 //Assert Deep sleep signal now to put Libra HW in lowest power state
4491 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4492 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4493
4494 //Vote off any PMIC voltage supplies
4495 vos_chipPowerDown(NULL, NULL, NULL);
4496
4497 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4498
4499 //Clean up HDD Nlink Service
4500 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
4501 nl_srv_exit();
4502
4503 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004504 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004505
4506 //Close the scheduler before calling vos_close to make sure no thread is
4507 // scheduled after the each module close is called i.e after all the data
4508 // structures are freed.
4509 vosStatus = vos_sched_close( pVosContext );
4510 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4511 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4512 "%s: Failed to close VOSS Scheduler",__func__);
4513 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4514 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004515#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004516#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4517 /* Destroy the wake lock */
4518 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4519#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004520 /* Destroy the wake lock */
4521 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004522#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004523
4524 //Close VOSS
4525 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4526 vos_close(pVosContext);
4527
Jeff Johnson295189b2012-06-20 16:38:30 -07004528 //Close Watchdog
4529 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4530 vos_watchdog_close(pVosContext);
4531
4532 /* Cancel the vote for XO Core ON.
4533 * This is done here to ensure there is no race condition since MC, TX and WD threads have
4534 * exited at this point
4535 */
4536 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
4537 " when WLAN is turned OFF\n");
4538 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4539 {
4540 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
4541 " Not returning failure."
4542 " Power consumed will be high\n");
4543 }
4544
4545 hdd_close_all_adapters( pHddCtx );
4546
4547
4548 //Free up dynamically allocated members inside HDD Adapter
4549 kfree(pHddCtx->cfg_ini);
4550 pHddCtx->cfg_ini= NULL;
4551
4552 /* free the power on lock from platform driver */
4553 if (free_riva_power_on_lock("wlan"))
4554 {
4555 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
4556 __func__);
4557 }
4558
Jeff Johnson88ba7742013-02-27 14:36:02 -08004559free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08004560 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004561 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004562 if (hdd_is_ssr_required())
4563 {
4564 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07004565 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07004566 msleep(5000);
4567 }
4568 hdd_set_ssr_required (VOS_FALSE);
4569}
4570
4571
4572/**---------------------------------------------------------------------------
4573
4574 \brief hdd_update_config_from_nv() - Function to update the contents of
4575 the running configuration with parameters taken from NV storage
4576
4577 \param - pHddCtx - Pointer to the HDD global context
4578
4579 \return - VOS_STATUS_SUCCESS if successful
4580
4581 --------------------------------------------------------------------------*/
4582static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
4583{
Jeff Johnson295189b2012-06-20 16:38:30 -07004584 v_BOOL_t itemIsValid = VOS_FALSE;
4585 VOS_STATUS status;
4586 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
4587 v_U8_t macLoop;
4588
4589 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
4590 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
4591 if(status != VOS_STATUS_SUCCESS)
4592 {
4593 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
4594 return VOS_STATUS_E_FAILURE;
4595 }
4596
4597 if (itemIsValid == VOS_TRUE)
4598 {
4599 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
4600 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
4601 VOS_MAX_CONCURRENCY_PERSONA);
4602 if(status != VOS_STATUS_SUCCESS)
4603 {
4604 /* Get MAC from NV fail, not update CFG info
4605 * INI MAC value will be used for MAC setting */
4606 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
4607 return VOS_STATUS_E_FAILURE;
4608 }
4609
4610 /* If first MAC is not valid, treat all others are not valid
4611 * Then all MACs will be got from ini file */
4612 if(vos_is_macaddr_zero(&macFromNV[0]))
4613 {
4614 /* MAC address in NV file is not configured yet */
4615 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
4616 return VOS_STATUS_E_INVAL;
4617 }
4618
4619 /* Get MAC address from NV, update CFG info */
4620 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
4621 {
4622 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
4623 {
4624 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
4625 /* This MAC is not valid, skip it
4626 * This MAC will be got from ini file */
4627 }
4628 else
4629 {
4630 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
4631 (v_U8_t *)&macFromNV[macLoop].bytes[0],
4632 VOS_MAC_ADDR_SIZE);
4633 }
4634 }
4635 }
4636 else
4637 {
4638 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
4639 return VOS_STATUS_E_FAILURE;
4640 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004641
Jeff Johnson295189b2012-06-20 16:38:30 -07004642
4643 return VOS_STATUS_SUCCESS;
4644}
4645
4646/**---------------------------------------------------------------------------
4647
4648 \brief hdd_post_voss_start_config() - HDD post voss start config helper
4649
4650 \param - pAdapter - Pointer to the HDD
4651
4652 \return - None
4653
4654 --------------------------------------------------------------------------*/
4655VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
4656{
4657 eHalStatus halStatus;
4658 v_U32_t listenInterval;
4659
Jeff Johnson295189b2012-06-20 16:38:30 -07004660
4661 // Send ready indication to the HDD. This will kick off the MAC
4662 // into a 'running' state and should kick off an initial scan.
4663 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
4664 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4665 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304666 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07004667 "code %08d [x%08x]",__func__, halStatus, halStatus );
4668 return VOS_STATUS_E_FAILURE;
4669 }
4670
4671 // Set default LI into HDD context,
4672 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
4673 // And RIVA will crash
4674 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
4675 pHddCtx->hdd_actual_LI_value = listenInterval;
4676
4677 return VOS_STATUS_SUCCESS;
4678}
4679
Jeff Johnson295189b2012-06-20 16:38:30 -07004680/* wake lock APIs for HDD */
4681void hdd_prevent_suspend(void)
4682{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004683#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004684 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004685#else
4686 wcnss_prevent_suspend();
4687#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004688}
4689
4690void hdd_allow_suspend(void)
4691{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004692#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004693 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004694#else
4695 wcnss_allow_suspend();
4696#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004697}
4698
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004699void hdd_allow_suspend_timeout(v_U32_t timeout)
4700{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004701#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07004702 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004703#else
4704 /* Do nothing as there is no API in wcnss for timeout*/
4705#endif
4706}
4707
Jeff Johnson295189b2012-06-20 16:38:30 -07004708/**---------------------------------------------------------------------------
4709
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004710 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
4711 information between Host and Riva
4712
4713 This function gets reported version of FW
4714 It also finds the version of Riva headers used to compile the host
4715 It compares the above two and prints a warning if they are different
4716 It gets the SW and HW version string
4717 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
4718 indicating the features they support through a bitmap
4719
4720 \param - pHddCtx - Pointer to HDD context
4721
4722 \return - void
4723
4724 --------------------------------------------------------------------------*/
4725
4726void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
4727{
4728
4729 tSirVersionType versionCompiled;
4730 tSirVersionType versionReported;
4731 tSirVersionString versionString;
4732 tANI_U8 fwFeatCapsMsgSupported = 0;
4733 VOS_STATUS vstatus;
4734
4735 /* retrieve and display WCNSS version information */
4736 do {
4737
4738 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
4739 &versionCompiled);
4740 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4741 {
4742 hddLog(VOS_TRACE_LEVEL_FATAL,
4743 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004744 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004745 break;
4746 }
4747
4748 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
4749 &versionReported);
4750 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4751 {
4752 hddLog(VOS_TRACE_LEVEL_FATAL,
4753 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004754 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004755 break;
4756 }
4757
4758 if ((versionCompiled.major != versionReported.major) ||
4759 (versionCompiled.minor != versionReported.minor) ||
4760 (versionCompiled.version != versionReported.version) ||
4761 (versionCompiled.revision != versionReported.revision))
4762 {
4763 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4764 "Host expected %u.%u.%u.%u\n",
4765 WLAN_MODULE_NAME,
4766 (int)versionReported.major,
4767 (int)versionReported.minor,
4768 (int)versionReported.version,
4769 (int)versionReported.revision,
4770 (int)versionCompiled.major,
4771 (int)versionCompiled.minor,
4772 (int)versionCompiled.version,
4773 (int)versionCompiled.revision);
4774 }
4775 else
4776 {
4777 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4778 WLAN_MODULE_NAME,
4779 (int)versionReported.major,
4780 (int)versionReported.minor,
4781 (int)versionReported.version,
4782 (int)versionReported.revision);
4783 }
4784
4785 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
4786 versionString,
4787 sizeof(versionString));
4788 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4789 {
4790 hddLog(VOS_TRACE_LEVEL_FATAL,
4791 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004792 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004793 break;
4794 }
4795
4796 pr_info("%s: WCNSS software version %s\n",
4797 WLAN_MODULE_NAME, versionString);
4798
4799 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
4800 versionString,
4801 sizeof(versionString));
4802 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4803 {
4804 hddLog(VOS_TRACE_LEVEL_FATAL,
4805 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004806 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004807 break;
4808 }
4809
4810 pr_info("%s: WCNSS hardware version %s\n",
4811 WLAN_MODULE_NAME, versionString);
4812
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004813 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
4814 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004815 send the message only if it the riva is 1.1
4816 minor numbers for different riva branches:
4817 0 -> (1.0)Mainline Build
4818 1 -> (1.1)Mainline Build
4819 2->(1.04) Stability Build
4820 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004821 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004822 ((versionReported.minor>=1) && (versionReported.version>=1)))
4823 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
4824 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004825
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004826 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08004827 {
4828#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4829 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
4830 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
4831#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004832 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08004833 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004834
4835 } while (0);
4836
4837}
4838
4839/**---------------------------------------------------------------------------
4840
Jeff Johnson295189b2012-06-20 16:38:30 -07004841 \brief hdd_wlan_startup() - HDD init function
4842
4843 This is the driver startup code executed once a WLAN device has been detected
4844
4845 \param - dev - Pointer to the underlying device
4846
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004847 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07004848
4849 --------------------------------------------------------------------------*/
4850
4851int hdd_wlan_startup(struct device *dev )
4852{
4853 VOS_STATUS status;
4854 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004855 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004856 hdd_context_t *pHddCtx = NULL;
4857 v_CONTEXT_t pVosContext= NULL;
4858#ifdef WLAN_BTAMP_FEATURE
4859 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
4860 WLANBAP_ConfigType btAmpConfig;
4861 hdd_config_t *pConfig;
4862#endif
4863 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07004864 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004865
4866 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07004867 /*
4868 * cfg80211: wiphy allocation
4869 */
4870 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
4871
4872 if(wiphy == NULL)
4873 {
4874 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004875 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004876 }
4877
4878 pHddCtx = wiphy_priv(wiphy);
4879
Jeff Johnson295189b2012-06-20 16:38:30 -07004880 //Initialize the adapter context to zeros.
4881 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
4882
Jeff Johnson295189b2012-06-20 16:38:30 -07004883 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004884 hdd_prevent_suspend();
4885 pHddCtx->isLoadUnloadInProgress = TRUE;
4886
4887 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4888
4889 /*Get vos context here bcoz vos_open requires it*/
4890 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4891
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08004892 if(pVosContext == NULL)
4893 {
4894 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
4895 goto err_free_hdd_context;
4896 }
4897
Jeff Johnson295189b2012-06-20 16:38:30 -07004898 //Save the Global VOSS context in adapter context for future.
4899 pHddCtx->pvosContext = pVosContext;
4900
4901 //Save the adapter context in global context for future.
4902 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
4903
Jeff Johnson295189b2012-06-20 16:38:30 -07004904 pHddCtx->parent_dev = dev;
4905
4906 init_completion(&pHddCtx->full_pwr_comp_var);
4907 init_completion(&pHddCtx->standby_comp_var);
4908 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004909 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004910 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004911
4912 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
4913
4914 // Load all config first as TL config is needed during vos_open
4915 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
4916 if(pHddCtx->cfg_ini == NULL)
4917 {
4918 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
4919 goto err_free_hdd_context;
4920 }
4921
4922 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
4923
4924 // Read and parse the qcom_cfg.ini file
4925 status = hdd_parse_config_ini( pHddCtx );
4926 if ( VOS_STATUS_SUCCESS != status )
4927 {
4928 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
4929 __func__, WLAN_INI_FILE);
4930 goto err_config;
4931 }
4932
Jeff Johnson295189b2012-06-20 16:38:30 -07004933 /*
4934 * cfg80211: Initialization and registration ...
4935 */
4936 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
4937 {
4938 hddLog(VOS_TRACE_LEVEL_FATAL,
4939 "%s: wlan_hdd_cfg80211_register return failure", __func__);
4940 goto err_wiphy_reg;
4941 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004942
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004943 // Update VOS trace levels based upon the cfg.ini
4944 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
4945 pHddCtx->cfg_ini->vosTraceEnableBAP);
4946 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
4947 pHddCtx->cfg_ini->vosTraceEnableTL);
4948 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
4949 pHddCtx->cfg_ini->vosTraceEnableWDI);
4950 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
4951 pHddCtx->cfg_ini->vosTraceEnableHDD);
4952 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
4953 pHddCtx->cfg_ini->vosTraceEnableSME);
4954 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
4955 pHddCtx->cfg_ini->vosTraceEnablePE);
4956 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
4957 pHddCtx->cfg_ini->vosTraceEnableWDA);
4958 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
4959 pHddCtx->cfg_ini->vosTraceEnableSYS);
4960 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
4961 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004962 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
4963 pHddCtx->cfg_ini->vosTraceEnableSAP);
4964 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
4965 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004966
Jeff Johnson295189b2012-06-20 16:38:30 -07004967 // Update WDI trace levels based upon the cfg.ini
4968 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
4969 pHddCtx->cfg_ini->wdiTraceEnableDAL);
4970 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
4971 pHddCtx->cfg_ini->wdiTraceEnableCTL);
4972 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
4973 pHddCtx->cfg_ini->wdiTraceEnableDAT);
4974 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
4975 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004976
Jeff Johnson88ba7742013-02-27 14:36:02 -08004977 if (VOS_FTM_MODE == hdd_get_conparam())
4978 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004979 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
4980 {
4981 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
4982 goto err_free_hdd_context;
4983 }
4984 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
4985 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08004986 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004987
Jeff Johnson88ba7742013-02-27 14:36:02 -08004988 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07004989 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4990 {
4991 status = vos_watchdog_open(pVosContext,
4992 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
4993
4994 if(!VOS_IS_STATUS_SUCCESS( status ))
4995 {
4996 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004997 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07004998 }
4999 }
5000
5001 pHddCtx->isLogpInProgress = FALSE;
5002 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5003
Jeff Johnson295189b2012-06-20 16:38:30 -07005004 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5005 if(!VOS_IS_STATUS_SUCCESS(status))
5006 {
5007 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005008 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005009 }
5010
Jeff Johnson295189b2012-06-20 16:38:30 -07005011 status = vos_open( &pVosContext, 0);
5012 if ( !VOS_IS_STATUS_SUCCESS( status ))
5013 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005014 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5015 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005016 }
5017
Jeff Johnson295189b2012-06-20 16:38:30 -07005018 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5019
5020 if ( NULL == pHddCtx->hHal )
5021 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005022 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005023 goto err_vosclose;
5024 }
5025
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005026 status = vos_preStart( pHddCtx->pvosContext );
5027 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5028 {
5029 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5030 goto err_vosclose;
5031 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005032
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005033 /* Note that the vos_preStart() sequence triggers the cfg download.
5034 The cfg download must occur before we update the SME config
5035 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005036 status = hdd_set_sme_config( pHddCtx );
5037
5038 if ( VOS_STATUS_SUCCESS != status )
5039 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005040 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5041 goto err_vosclose;
5042 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005043
5044 //Initialize the WMM module
5045 status = hdd_wmm_init(pHddCtx);
5046 if (!VOS_IS_STATUS_SUCCESS(status))
5047 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005048 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005049 goto err_vosclose;
5050 }
5051
Jeff Johnson295189b2012-06-20 16:38:30 -07005052 /* In the integrated architecture we update the configuration from
5053 the INI file and from NV before vOSS has been started so that
5054 the final contents are available to send down to the cCPU */
5055
5056 // Apply the cfg.ini to cfg.dat
5057 if (FALSE == hdd_update_config_dat(pHddCtx))
5058 {
5059 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5060 goto err_vosclose;
5061 }
5062
5063 // Apply the NV to cfg.dat
5064 /* Prima Update MAC address only at here */
5065 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5066 {
5067#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5068 /* There was not a valid set of MAC Addresses in NV. See if the
5069 default addresses were modified by the cfg.ini settings. If so,
5070 we'll use them, but if not, we'll autogenerate a set of MAC
5071 addresses based upon the device serial number */
5072
5073 static const v_MACADDR_t default_address =
5074 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5075 unsigned int serialno;
5076 int i;
5077
5078 serialno = wcnss_get_serial_number();
5079 if ((0 != serialno) &&
5080 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5081 sizeof(default_address))))
5082 {
5083 /* cfg.ini has the default address, invoke autogen logic */
5084
5085 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5086 bytes of the serial number that can be used to generate
5087 the other 3 bytes of the MAC address. Mask off all but
5088 the lower 3 bytes (this will also make sure we don't
5089 overflow in the next step) */
5090 serialno &= 0x00FFFFFF;
5091
5092 /* we need a unique address for each session */
5093 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5094
5095 /* autogen all addresses */
5096 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5097 {
5098 /* start with the entire default address */
5099 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5100 /* then replace the lower 3 bytes */
5101 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5102 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5103 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5104
5105 serialno++;
5106 }
5107
5108 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5109 MAC_ADDRESS_STR,
5110 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5111 }
5112 else
5113#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5114 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005115 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005116 "%s: Invalid MAC address in NV, using MAC from ini file "
5117 MAC_ADDRESS_STR, __func__,
5118 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5119 }
5120 }
5121 {
5122 eHalStatus halStatus;
5123 // Set the MAC Address
5124 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5125 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5126 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5127 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5128
5129 if (!HAL_STATUS_SUCCESS( halStatus ))
5130 {
5131 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5132 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005133 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005134 }
5135 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005136
5137 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5138 Note: Firmware image will be read and downloaded inside vos_start API */
5139 status = vos_start( pHddCtx->pvosContext );
5140 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5141 {
5142 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5143 goto err_vosclose;
5144 }
5145
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005146 /* Exchange capability info between Host and FW and also get versioning info from FW */
5147 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005148
5149 status = hdd_post_voss_start_config( pHddCtx );
5150 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5151 {
5152 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5153 __func__);
5154 goto err_vosstop;
5155 }
5156
Jeff Johnson295189b2012-06-20 16:38:30 -07005157 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5158 {
5159 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5160 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5161 }
5162 else
5163 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005164 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5165 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5166 if (pAdapter != NULL)
5167 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305168 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005169 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305170 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5171 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5172 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005173
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305174 /* Generate the P2P Device Address. This consists of the device's
5175 * primary MAC address with the locally administered bit set.
5176 */
5177 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005178 }
5179 else
5180 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305181 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5182 if (p2p_dev_addr != NULL)
5183 {
5184 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5185 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5186 }
5187 else
5188 {
5189 hddLog(VOS_TRACE_LEVEL_FATAL,
5190 "%s: Failed to allocate mac_address for p2p_device",
5191 __func__);
5192 goto err_close_adapter;
5193 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005194 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005195
5196 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5197 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5198 if ( NULL == pP2pAdapter )
5199 {
5200 hddLog(VOS_TRACE_LEVEL_FATAL,
5201 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005202 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005203 goto err_close_adapter;
5204 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005205 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005206 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005207
5208 if( pAdapter == NULL )
5209 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005210 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5211 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005212 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005213
Jeff Johnson295189b2012-06-20 16:38:30 -07005214#ifdef WLAN_BTAMP_FEATURE
5215 vStatus = WLANBAP_Open(pVosContext);
5216 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5217 {
5218 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5219 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005220 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005221 }
5222
5223 vStatus = BSL_Init(pVosContext);
5224 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5225 {
5226 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5227 "%s: Failed to Init BSL",__func__);
5228 goto err_bap_close;
5229 }
5230 vStatus = WLANBAP_Start(pVosContext);
5231 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5232 {
5233 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5234 "%s: Failed to start TL",__func__);
5235 goto err_bap_close;
5236 }
5237
5238 pConfig = pHddCtx->cfg_ini;
5239 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5240 status = WLANBAP_SetConfig(&btAmpConfig);
5241
5242#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005243
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005244#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5245 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5246 {
5247 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5248 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5249 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5250 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5251 }
5252#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005253#ifdef FEATURE_WLAN_SCAN_PNO
5254 /*SME must send channel update configuration to RIVA*/
5255 sme_UpdateChannelConfig(pHddCtx->hHal);
5256#endif
5257
Jeff Johnson295189b2012-06-20 16:38:30 -07005258 /* Register with platform driver as client for Suspend/Resume */
5259 status = hddRegisterPmOps(pHddCtx);
5260 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5261 {
5262 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5263#ifdef WLAN_BTAMP_FEATURE
5264 goto err_bap_stop;
5265#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005266 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005267#endif //WLAN_BTAMP_FEATURE
5268 }
5269
5270 /* Register TM level change handler function to the platform */
5271 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5272 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5273 {
5274 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5275 goto err_unregister_pmops;
5276 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005277
5278 /* register for riva power on lock to platform driver */
5279 if (req_riva_power_on_lock("wlan"))
5280 {
5281 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5282 __func__);
5283 goto err_unregister_pmops;
5284 }
5285
Jeff Johnson295189b2012-06-20 16:38:30 -07005286 // register net device notifier for device change notification
5287 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5288
5289 if(ret < 0)
5290 {
5291 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5292 goto err_free_power_on_lock;
5293 }
5294
5295 //Initialize the nlink service
5296 if(nl_srv_init() != 0)
5297 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305298 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005299 goto err_reg_netdev;
5300 }
5301
5302 //Initialize the BTC service
5303 if(btc_activate_service(pHddCtx) != 0)
5304 {
5305 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5306 goto err_nl_srv;
5307 }
5308
5309#ifdef PTT_SOCK_SVC_ENABLE
5310 //Initialize the PTT service
5311 if(ptt_sock_activate_svc(pHddCtx) != 0)
5312 {
5313 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5314 goto err_nl_srv;
5315 }
5316#endif
5317
Jeff Johnson295189b2012-06-20 16:38:30 -07005318 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005319 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005320 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005321 /* Action frame registered in one adapter which will
5322 * applicable to all interfaces
5323 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005324 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005325 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005326
5327 mutex_init(&pHddCtx->sap_lock);
5328
5329 pHddCtx->isLoadUnloadInProgress = FALSE;
5330
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005331#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005332#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5333 /* Initialize the wake lcok */
5334 wake_lock_init(&pHddCtx->rx_wake_lock,
5335 WAKE_LOCK_SUSPEND,
5336 "qcom_rx_wakelock");
5337#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005338 /* Initialize the wake lcok */
5339 wake_lock_init(&pHddCtx->sap_wake_lock,
5340 WAKE_LOCK_SUSPEND,
5341 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005342#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005343
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005344 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5345 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005346
5347 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5348 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005349
5350 // Initialize the restart logic
5351 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305352
Jeff Johnson295189b2012-06-20 16:38:30 -07005353 goto success;
5354
5355err_nl_srv:
5356 nl_srv_exit();
5357
5358err_reg_netdev:
5359 unregister_netdevice_notifier(&hdd_netdev_notifier);
5360
5361err_free_power_on_lock:
5362 free_riva_power_on_lock("wlan");
5363
5364err_unregister_pmops:
5365 hddDevTmUnregisterNotifyCallback(pHddCtx);
5366 hddDeregisterPmOps(pHddCtx);
5367
5368#ifdef WLAN_BTAMP_FEATURE
5369err_bap_stop:
5370 WLANBAP_Stop(pVosContext);
5371#endif
5372
5373#ifdef WLAN_BTAMP_FEATURE
5374err_bap_close:
5375 WLANBAP_Close(pVosContext);
5376#endif
5377
Jeff Johnson295189b2012-06-20 16:38:30 -07005378err_close_adapter:
5379 hdd_close_all_adapters( pHddCtx );
5380
5381err_vosstop:
5382 vos_stop(pVosContext);
5383
5384err_vosclose:
5385 status = vos_sched_close( pVosContext );
5386 if (!VOS_IS_STATUS_SUCCESS(status)) {
5387 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5388 "%s: Failed to close VOSS Scheduler", __func__);
5389 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5390 }
5391 vos_close(pVosContext );
5392
Jeff Johnson295189b2012-06-20 16:38:30 -07005393err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005394 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005395
5396err_wdclose:
5397 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5398 vos_watchdog_close(pVosContext);
5399
Jeff Johnson295189b2012-06-20 16:38:30 -07005400err_wiphy_reg:
5401 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005402
5403err_config:
5404 kfree(pHddCtx->cfg_ini);
5405 pHddCtx->cfg_ini= NULL;
5406
5407err_free_hdd_context:
5408 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005409 wiphy_free(wiphy) ;
5410 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005411 VOS_BUG(1);
5412
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005413 if (hdd_is_ssr_required())
5414 {
5415 /* WDI timeout had happened during load, so SSR is needed here */
5416 subsystem_restart("wcnss");
5417 msleep(5000);
5418 }
5419 hdd_set_ssr_required (VOS_FALSE);
5420
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005421 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005422
5423success:
5424 EXIT();
5425 return 0;
5426}
5427
5428/**---------------------------------------------------------------------------
5429
Jeff Johnson32d95a32012-09-10 13:15:23 -07005430 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07005431
Jeff Johnson32d95a32012-09-10 13:15:23 -07005432 This is the driver entry point - called in different timeline depending
5433 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07005434
5435 \param - None
5436
5437 \return - 0 for success, non zero for failure
5438
5439 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07005440static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005441{
5442 VOS_STATUS status;
5443 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005444 struct device *dev = NULL;
5445 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005446#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5447 int max_retries = 0;
5448#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005449
5450 ENTER();
5451
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005452#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005453 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07005454#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005455
5456 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
5457 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
5458
5459 //Power Up Libra WLAN card first if not already powered up
5460 status = vos_chipPowerUp(NULL,NULL,NULL);
5461 if (!VOS_IS_STATUS_SUCCESS(status))
5462 {
5463 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
5464 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005465 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005466 }
5467
Jeff Johnson295189b2012-06-20 16:38:30 -07005468#ifdef ANI_BUS_TYPE_PCI
5469
5470 dev = wcnss_wlan_get_device();
5471
5472#endif // ANI_BUS_TYPE_PCI
5473
5474#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005475
5476#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5477 /* wait until WCNSS driver downloads NV */
5478 while (!wcnss_device_ready() && 5 >= ++max_retries) {
5479 msleep(1000);
5480 }
5481 if (max_retries >= 5) {
5482 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
5483 return -ENODEV;
5484 }
5485#endif
5486
Jeff Johnson295189b2012-06-20 16:38:30 -07005487 dev = wcnss_wlan_get_device();
5488#endif // ANI_BUS_TYPE_PLATFORM
5489
5490
5491 do {
5492 if (NULL == dev) {
5493 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
5494 ret_status = -1;
5495 break;
5496 }
5497
5498#ifdef MEMORY_DEBUG
5499 vos_mem_init();
5500#endif
5501
5502#ifdef TIMER_MANAGER
5503 vos_timer_manager_init();
5504#endif
5505
5506 /* Preopen VOSS so that it is ready to start at least SAL */
5507 status = vos_preOpen(&pVosContext);
5508
5509 if (!VOS_IS_STATUS_SUCCESS(status))
5510 {
5511 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
5512 ret_status = -1;
5513 break;
5514 }
5515
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005516#ifndef MODULE
5517 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
5518 */
5519 hdd_set_conparam((v_UINT_t)con_mode);
5520#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005521
5522 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005523 if (hdd_wlan_startup(dev))
5524 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005525 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005526 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005527 vos_preClose( &pVosContext );
5528 ret_status = -1;
5529 break;
5530 }
5531
5532 /* Cancel the vote for XO Core ON
5533 * This is done here for safety purposes in case we re-initialize without turning
5534 * it OFF in any error scenario.
5535 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005536 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07005537 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005538 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07005539 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5540 {
5541 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
5542 " Power consumed will be high\n");
5543 }
5544 } while (0);
5545
5546 if (0 != ret_status)
5547 {
5548 //Assert Deep sleep signal now to put Libra HW in lowest power state
5549 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5550 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
5551
5552 //Vote off any PMIC voltage supplies
5553 vos_chipPowerDown(NULL, NULL, NULL);
5554#ifdef TIMER_MANAGER
5555 vos_timer_exit();
5556#endif
5557#ifdef MEMORY_DEBUG
5558 vos_mem_exit();
5559#endif
5560
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005561#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005562 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005563#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005564 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
5565 }
5566 else
5567 {
5568 //Send WLAN UP indication to Nlink Service
5569 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
5570
5571 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
5572
5573 }
5574
5575 EXIT();
5576
5577 return ret_status;
5578}
5579
Jeff Johnson32d95a32012-09-10 13:15:23 -07005580/**---------------------------------------------------------------------------
5581
5582 \brief hdd_module_init() - Init Function
5583
5584 This is the driver entry point (invoked when module is loaded using insmod)
5585
5586 \param - None
5587
5588 \return - 0 for success, non zero for failure
5589
5590 --------------------------------------------------------------------------*/
5591#ifdef MODULE
5592static int __init hdd_module_init ( void)
5593{
5594 return hdd_driver_init();
5595}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005596#else /* #ifdef MODULE */
5597static int __init hdd_module_init ( void)
5598{
5599 /* Driver initialization is delayed to fwpath_changed_handler */
5600 return 0;
5601}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005602#endif /* #ifdef MODULE */
5603
Jeff Johnson295189b2012-06-20 16:38:30 -07005604
5605/**---------------------------------------------------------------------------
5606
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005607 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005608
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005609 This is the driver exit point (invoked when module is unloaded using rmmod
5610 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07005611
5612 \param - None
5613
5614 \return - None
5615
5616 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005617static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005618{
5619 hdd_context_t *pHddCtx = NULL;
5620 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005621
5622 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
5623
5624 //Get the global vos context
5625 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5626
5627 if(!pVosContext)
5628 {
5629 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
5630 goto done;
5631 }
5632
5633 //Get the HDD context.
5634 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
5635
5636 if(!pHddCtx)
5637 {
5638 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
5639 }
5640 else
5641 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005642 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07005643 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07005644 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
5645 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07005646 }
5647
5648 pHddCtx->isLoadUnloadInProgress = TRUE;
5649 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5650
5651 //Do all the cleanup before deregistering the driver
5652 hdd_wlan_exit(pHddCtx);
5653 }
5654
Jeff Johnson295189b2012-06-20 16:38:30 -07005655 vos_preClose( &pVosContext );
5656
5657#ifdef TIMER_MANAGER
5658 vos_timer_exit();
5659#endif
5660#ifdef MEMORY_DEBUG
5661 vos_mem_exit();
5662#endif
5663
5664done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005665#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005666 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005667#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005668 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
5669}
5670
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005671/**---------------------------------------------------------------------------
5672
5673 \brief hdd_module_exit() - Exit function
5674
5675 This is the driver exit point (invoked when module is unloaded using rmmod)
5676
5677 \param - None
5678
5679 \return - None
5680
5681 --------------------------------------------------------------------------*/
5682static void __exit hdd_module_exit(void)
5683{
5684 hdd_driver_exit();
5685}
5686
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005687#ifdef MODULE
5688static int fwpath_changed_handler(const char *kmessage,
5689 struct kernel_param *kp)
5690{
Jeff Johnson76052702013-04-16 13:55:05 -07005691 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005692}
5693
5694static int con_mode_handler(const char *kmessage,
5695 struct kernel_param *kp)
5696{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07005697 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005698}
5699#else /* #ifdef MODULE */
5700/**---------------------------------------------------------------------------
5701
Jeff Johnson76052702013-04-16 13:55:05 -07005702 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005703
Jeff Johnson76052702013-04-16 13:55:05 -07005704 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005705 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07005706 - invoked when module parameter fwpath is modified from userspace to signal
5707 initializing the WLAN driver or when con_mode is modified from userspace
5708 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005709
5710 \return - 0 for success, non zero for failure
5711
5712 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07005713static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005714{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005715 int ret_status;
5716
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005717 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005718 ret_status = hdd_driver_init();
5719 wlan_hdd_inited = ret_status ? 0 : 1;
5720 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005721 }
5722
5723 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07005724
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005725 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07005726
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005727 ret_status = hdd_driver_init();
5728 wlan_hdd_inited = ret_status ? 0 : 1;
5729 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005730}
5731
Jeff Johnson295189b2012-06-20 16:38:30 -07005732/**---------------------------------------------------------------------------
5733
Jeff Johnson76052702013-04-16 13:55:05 -07005734 \brief fwpath_changed_handler() - Handler Function
5735
5736 Handle changes to the fwpath parameter
5737
5738 \return - 0 for success, non zero for failure
5739
5740 --------------------------------------------------------------------------*/
5741static int fwpath_changed_handler(const char *kmessage,
5742 struct kernel_param *kp)
5743{
5744 int ret;
5745
5746 ret = param_set_copystring(kmessage, kp);
5747 if (0 == ret)
5748 ret = kickstart_driver();
5749 return ret;
5750}
5751
5752/**---------------------------------------------------------------------------
5753
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005754 \brief con_mode_handler() -
5755
5756 Handler function for module param con_mode when it is changed by userspace
5757 Dynamically linked - do nothing
5758 Statically linked - exit and init driver, as in rmmod and insmod
5759
Jeff Johnson76052702013-04-16 13:55:05 -07005760 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005761
Jeff Johnson76052702013-04-16 13:55:05 -07005762 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005763
5764 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07005765static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005766{
Jeff Johnson76052702013-04-16 13:55:05 -07005767 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005768
Jeff Johnson76052702013-04-16 13:55:05 -07005769 ret = param_set_int(kmessage, kp);
5770 if (0 == ret)
5771 ret = kickstart_driver();
5772 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005773}
5774#endif /* #ifdef MODULE */
5775
5776/**---------------------------------------------------------------------------
5777
Jeff Johnson295189b2012-06-20 16:38:30 -07005778 \brief hdd_get_conparam() -
5779
5780 This is the driver exit point (invoked when module is unloaded using rmmod)
5781
5782 \param - None
5783
5784 \return - tVOS_CON_MODE
5785
5786 --------------------------------------------------------------------------*/
5787tVOS_CON_MODE hdd_get_conparam ( void )
5788{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005789#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07005790 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005791#else
5792 return (tVOS_CON_MODE)curr_con_mode;
5793#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005794}
5795void hdd_set_conparam ( v_UINT_t newParam )
5796{
5797 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005798#ifndef MODULE
5799 curr_con_mode = con_mode;
5800#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005801}
5802/**---------------------------------------------------------------------------
5803
5804 \brief hdd_softap_sta_deauth() - function
5805
5806 This to take counter measure to handle deauth req from HDD
5807
5808 \param - pAdapter - Pointer to the HDD
5809
5810 \param - enable - boolean value
5811
5812 \return - None
5813
5814 --------------------------------------------------------------------------*/
5815
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005816VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07005817{
Jeff Johnson295189b2012-06-20 16:38:30 -07005818 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005819 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07005820
5821 ENTER();
5822
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305823 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07005824
5825 //Ignore request to deauth bcmc station
5826 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005827 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005828
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005829 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07005830
5831 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005832 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005833}
5834
5835/**---------------------------------------------------------------------------
5836
5837 \brief hdd_softap_sta_disassoc() - function
5838
5839 This to take counter measure to handle deauth req from HDD
5840
5841 \param - pAdapter - Pointer to the HDD
5842
5843 \param - enable - boolean value
5844
5845 \return - None
5846
5847 --------------------------------------------------------------------------*/
5848
5849void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
5850{
5851 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5852
5853 ENTER();
5854
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305855 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07005856
5857 //Ignore request to disassoc bcmc station
5858 if( pDestMacAddress[0] & 0x1 )
5859 return;
5860
5861 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
5862}
5863
5864void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
5865{
5866 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5867
5868 ENTER();
5869
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305870 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07005871
5872 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
5873}
5874
Jeff Johnson295189b2012-06-20 16:38:30 -07005875/**---------------------------------------------------------------------------
5876 *
5877 * \brief hdd_get__concurrency_mode() -
5878 *
5879 *
5880 * \param - None
5881 *
5882 * \return - CONCURRENCY MODE
5883 *
5884 * --------------------------------------------------------------------------*/
5885tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
5886{
5887 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5888 hdd_context_t *pHddCtx;
5889
5890 if (NULL != pVosContext)
5891 {
5892 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5893 if (NULL != pHddCtx)
5894 {
5895 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
5896 }
5897 }
5898
5899 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005900 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005901 return VOS_STA;
5902}
5903
5904/* Decide whether to allow/not the apps power collapse.
5905 * Allow apps power collapse if we are in connected state.
5906 * if not, allow only if we are in IMPS */
5907v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
5908{
5909 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08005910 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005911 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07005912 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5913 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5914 hdd_adapter_t *pAdapter = NULL;
5915 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08005916 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005917
Jeff Johnson295189b2012-06-20 16:38:30 -07005918 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5919 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005920
Yathish9f22e662012-12-10 14:21:35 -08005921 concurrent_state = hdd_get_concurrency_mode();
5922
5923#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5924 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
5925 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
5926 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
5927 return TRUE;
5928#endif
5929
Jeff Johnson295189b2012-06-20 16:38:30 -07005930 /*loop through all adapters. TBD fix for Concurrency */
5931 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5932 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5933 {
5934 pAdapter = pAdapterNode->pAdapter;
5935 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
5936 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5937 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005938 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07005939 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08005940 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005941 (eANI_BOOLEAN_TRUE == scanRspPending) ||
5942 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07005943 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005944 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005945 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
5946 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07005947 return FALSE;
5948 }
5949 }
5950 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5951 pAdapterNode = pNext;
5952 }
5953 return TRUE;
5954}
5955
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08005956/* Decides whether to send suspend notification to Riva
5957 * if any adapter is in BMPS; then it is required */
5958v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
5959{
5960 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
5961 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5962
5963 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
5964 {
5965 return TRUE;
5966 }
5967 return FALSE;
5968}
5969
Jeff Johnson295189b2012-06-20 16:38:30 -07005970void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5971{
5972 switch(mode)
5973 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005974 case VOS_STA_MODE:
5975 case VOS_P2P_CLIENT_MODE:
5976 case VOS_P2P_GO_MODE:
5977 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07005978 pHddCtx->concurrency_mode |= (1 << mode);
5979 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07005980 break;
5981 default:
5982 break;
5983
5984 }
5985 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5986 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5987}
5988
5989
5990void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5991{
5992 switch(mode)
5993 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005994 case VOS_STA_MODE:
5995 case VOS_P2P_CLIENT_MODE:
5996 case VOS_P2P_GO_MODE:
5997 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005998 pHddCtx->no_of_sessions[mode]--;
5999 if (!(pHddCtx->no_of_sessions[mode]))
6000 pHddCtx->concurrency_mode &= (~(1 << mode));
6001 break;
6002 default:
6003 break;
6004 }
6005 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6006 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6007}
6008
Jeff Johnsone7245742012-09-05 17:12:55 -07006009/**---------------------------------------------------------------------------
6010 *
6011 * \brief wlan_hdd_restart_init
6012 *
6013 * This function initalizes restart timer/flag. An internal function.
6014 *
6015 * \param - pHddCtx
6016 *
6017 * \return - None
6018 *
6019 * --------------------------------------------------------------------------*/
6020
6021static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6022{
6023 /* Initialize */
6024 pHddCtx->hdd_restart_retries = 0;
6025 atomic_set(&pHddCtx->isRestartInProgress, 0);
6026 vos_timer_init(&pHddCtx->hdd_restart_timer,
6027 VOS_TIMER_TYPE_SW,
6028 wlan_hdd_restart_timer_cb,
6029 pHddCtx);
6030}
6031/**---------------------------------------------------------------------------
6032 *
6033 * \brief wlan_hdd_restart_deinit
6034 *
6035 * This function cleans up the resources used. An internal function.
6036 *
6037 * \param - pHddCtx
6038 *
6039 * \return - None
6040 *
6041 * --------------------------------------------------------------------------*/
6042
6043static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6044{
6045
6046 VOS_STATUS vos_status;
6047 /* Block any further calls */
6048 atomic_set(&pHddCtx->isRestartInProgress, 1);
6049 /* Cleanup */
6050 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6051 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006052 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006053 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6054 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006055 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006056
6057}
6058
6059/**---------------------------------------------------------------------------
6060 *
6061 * \brief wlan_hdd_framework_restart
6062 *
6063 * This function uses a cfg80211 API to start a framework initiated WLAN
6064 * driver module unload/load.
6065 *
6066 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6067 *
6068 *
6069 * \param - pHddCtx
6070 *
6071 * \return - VOS_STATUS_SUCCESS: Success
6072 * VOS_STATUS_E_EMPTY: Adapter is Empty
6073 * VOS_STATUS_E_NOMEM: No memory
6074
6075 * --------------------------------------------------------------------------*/
6076
6077static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6078{
6079 VOS_STATUS status = VOS_STATUS_SUCCESS;
6080 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006081 int len = (sizeof (struct ieee80211_mgmt));
6082 struct ieee80211_mgmt *mgmt = NULL;
6083
6084 /* Prepare the DEAUTH managment frame with reason code */
6085 mgmt = kzalloc(len, GFP_KERNEL);
6086 if(mgmt == NULL)
6087 {
6088 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6089 "%s: memory allocation failed (%d bytes)", __func__, len);
6090 return VOS_STATUS_E_NOMEM;
6091 }
6092 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006093
6094 /* Iterate over all adapters/devices */
6095 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6096 do
6097 {
6098 if( (status == VOS_STATUS_SUCCESS) &&
6099 pAdapterNode &&
6100 pAdapterNode->pAdapter)
6101 {
6102 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6103 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6104 pAdapterNode->pAdapter->dev->name,
6105 pAdapterNode->pAdapter->device_mode,
6106 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006107 /*
6108 * CFG80211 event to restart the driver
6109 *
6110 * 'cfg80211_send_unprot_deauth' sends a
6111 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6112 * of SME(Linux Kernel) state machine.
6113 *
6114 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6115 * the driver.
6116 *
6117 */
6118
6119 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006120 }
6121 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6122 pAdapterNode = pNext;
6123 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6124
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006125
6126 /* Free the allocated management frame */
6127 kfree(mgmt);
6128
Jeff Johnsone7245742012-09-05 17:12:55 -07006129 /* Retry until we unload or reach max count */
6130 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6131 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6132
6133 return status;
6134
6135}
6136/**---------------------------------------------------------------------------
6137 *
6138 * \brief wlan_hdd_restart_timer_cb
6139 *
6140 * Restart timer callback. An internal function.
6141 *
6142 * \param - User data:
6143 *
6144 * \return - None
6145 *
6146 * --------------------------------------------------------------------------*/
6147
6148void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6149{
6150 hdd_context_t *pHddCtx = usrDataForCallback;
6151 wlan_hdd_framework_restart(pHddCtx);
6152 return;
6153
6154}
6155
6156
6157/**---------------------------------------------------------------------------
6158 *
6159 * \brief wlan_hdd_restart_driver
6160 *
6161 * This function sends an event to supplicant to restart the WLAN driver.
6162 *
6163 * This function is called from vos_wlanRestart.
6164 *
6165 * \param - pHddCtx
6166 *
6167 * \return - VOS_STATUS_SUCCESS: Success
6168 * VOS_STATUS_E_EMPTY: Adapter is Empty
6169 * VOS_STATUS_E_ALREADY: Request already in progress
6170
6171 * --------------------------------------------------------------------------*/
6172VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6173{
6174 VOS_STATUS status = VOS_STATUS_SUCCESS;
6175
6176 /* A tight check to make sure reentrancy */
6177 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6178 {
6179 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6180 "%s: WLAN restart is already in progress", __func__);
6181
6182 return VOS_STATUS_E_ALREADY;
6183 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006184 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006185#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006186 wcnss_reset_intr();
6187#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006188
Jeff Johnsone7245742012-09-05 17:12:55 -07006189 return status;
6190}
6191
6192
Jeff Johnson295189b2012-06-20 16:38:30 -07006193//Register the module init/exit functions
6194module_init(hdd_module_init);
6195module_exit(hdd_module_exit);
6196
6197MODULE_LICENSE("Dual BSD/GPL");
6198MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6199MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6200
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006201module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6202 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006203
Jeff Johnson76052702013-04-16 13:55:05 -07006204module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006205 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);