blob: 47030030f4f61b8fff2b9828325d1a08cf5f604d [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
Yue Ma54db3d42013-04-19 16:44:28 -0700145#define MAX_RESTART_DRIVER_EVENT_LENGTH 30
146
Jeff Johnson295189b2012-06-20 16:38:30 -0700147/* the Android framework expects this param even though we don't use it */
148#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700149static char fwpath_buffer[BUF_LEN];
150static struct kparam_string fwpath = {
151 .string = fwpath_buffer,
152 .maxlen = BUF_LEN,
153};
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700154#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700155static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700156#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700157
Jeff Johnsone7245742012-09-05 17:12:55 -0700158/*
159 * The rate at which the driver sends RESTART event to supplicant
160 * once the function 'vos_wlanRestart()' is called
161 *
162 */
163#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
164#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800165#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700166static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700167#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700168/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700169static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700170
171//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700172static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
173static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
174static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
175void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800176void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700177
Jeff Johnson295189b2012-06-20 16:38:30 -0700178v_U16_t hdd_select_queue(struct net_device *dev,
179 struct sk_buff *skb);
180
181#ifdef WLAN_FEATURE_PACKET_FILTERING
182static void hdd_set_multicast_list(struct net_device *dev);
183#endif
184
185void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700186int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700187
188extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800189#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
190void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
191static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
192static VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700193static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
194 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
195 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800196#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700197static int hdd_netdev_notifier_call(struct notifier_block * nb,
198 unsigned long state,
199 void *ndev)
200{
201 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700202 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700203 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700204#ifdef WLAN_BTAMP_FEATURE
205 VOS_STATUS status;
206 hdd_context_t *pHddCtx;
207#endif
208
209 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700210 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700211 (strncmp(dev->name, "p2p", 3)))
212 return NOTIFY_DONE;
213
214 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700215 return NOTIFY_DONE;
216
Jeff Johnson295189b2012-06-20 16:38:30 -0700217 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700218 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700219
Jeff Johnson27cee452013-03-27 11:10:24 -0700220 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700221 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800222 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700223 VOS_ASSERT(0);
224 return NOTIFY_DONE;
225 }
226
Jeff Johnson27cee452013-03-27 11:10:24 -0700227 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
228 if (NULL == pHddCtx)
229 {
230 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
231 VOS_ASSERT(0);
232 return NOTIFY_DONE;
233 }
234
235 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
236 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700237
238 switch (state) {
239 case NETDEV_REGISTER:
240 break;
241
242 case NETDEV_UNREGISTER:
243 break;
244
245 case NETDEV_UP:
246 break;
247
248 case NETDEV_DOWN:
249 break;
250
251 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700252 if(TRUE == pAdapter->isLinkUpSvcNeeded)
253 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700254 break;
255
256 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700257 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700258 {
259 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800260 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700261 hdd_abort_mac_scan(pAdapter->pHddCtx);
262 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800263 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700264 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
265 if(!result)
266 {
267 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800268 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700269 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700270 }
271 }
272 else
273 {
274 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700275 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700276 }
277#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700278 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700279 status = WLANBAP_StopAmp();
280 if(VOS_STATUS_SUCCESS != status )
281 {
282 pHddCtx->isAmpAllowed = VOS_TRUE;
283 hddLog(VOS_TRACE_LEVEL_FATAL,
284 "%s: Failed to stop AMP", __func__);
285 }
286 else
287 {
288 //a state m/c implementation in PAL is TBD to avoid this delay
289 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700290 if ( pHddCtx->isAmpAllowed )
291 {
292 WLANBAP_DeregisterFromHCI();
293 pHddCtx->isAmpAllowed = VOS_FALSE;
294 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700295 }
296#endif //WLAN_BTAMP_FEATURE
297 break;
298
299 default:
300 break;
301 }
302
303 return NOTIFY_DONE;
304}
305
306struct notifier_block hdd_netdev_notifier = {
307 .notifier_call = hdd_netdev_notifier_call,
308};
309
310/*---------------------------------------------------------------------------
311 * Function definitions
312 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700313void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
314void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700315//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700316static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700317#ifndef MODULE
318/* current con_mode - used only for statically linked driver
319 * con_mode is changed by userspace to indicate a mode change which will
320 * result in calling the module exit and init functions. The module
321 * exit function will clean up based on the value of con_mode prior to it
322 * being changed by userspace. So curr_con_mode records the current con_mode
323 * for exit when con_mode becomes the next mode for init
324 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700325static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700326#endif
327
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800328/**---------------------------------------------------------------------------
329
330 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
331
332 Called immediately after the cfg.ini is read in order to configure
333 the desired trace levels.
334
335 \param - moduleId - module whose trace level is being configured
336 \param - bitmask - bitmask of log levels to be enabled
337
338 \return - void
339
340 --------------------------------------------------------------------------*/
341static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
342{
343 wpt_tracelevel level;
344
345 /* if the bitmask is the default value, then a bitmask was not
346 specified in cfg.ini, so leave the logging level alone (it
347 will remain at the "compiled in" default value) */
348 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
349 {
350 return;
351 }
352
353 /* a mask was specified. start by disabling all logging */
354 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
355
356 /* now cycle through the bitmask until all "set" bits are serviced */
357 level = VOS_TRACE_LEVEL_FATAL;
358 while (0 != bitmask)
359 {
360 if (bitmask & 1)
361 {
362 vos_trace_setValue(moduleId, level, 1);
363 }
364 level++;
365 bitmask >>= 1;
366 }
367}
368
369
Jeff Johnson295189b2012-06-20 16:38:30 -0700370/**---------------------------------------------------------------------------
371
372 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
373
374 Called immediately after the cfg.ini is read in order to configure
375 the desired trace levels in the WDI.
376
377 \param - moduleId - module whose trace level is being configured
378 \param - bitmask - bitmask of log levels to be enabled
379
380 \return - void
381
382 --------------------------------------------------------------------------*/
383static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
384{
385 wpt_tracelevel level;
386
387 /* if the bitmask is the default value, then a bitmask was not
388 specified in cfg.ini, so leave the logging level alone (it
389 will remain at the "compiled in" default value) */
390 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
391 {
392 return;
393 }
394
395 /* a mask was specified. start by disabling all logging */
396 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
397
398 /* now cycle through the bitmask until all "set" bits are serviced */
399 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
400 while (0 != bitmask)
401 {
402 if (bitmask & 1)
403 {
404 wpalTraceSetLevel(moduleId, level, 1);
405 }
406 level++;
407 bitmask >>= 1;
408 }
409}
Jeff Johnson295189b2012-06-20 16:38:30 -0700410
Gopichand Nakkalad86a14e2013-04-18 16:41:54 +0530411void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
412{
413 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
414 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
415 hdd_config_t *cfg_param;
416 eCsrPhyMode phyMode;
417
418 if (NULL == pHddCtx)
419 {
420 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
421 "HDD Context is null !!");
422 return ;
423 }
424
425 cfg_param = pHddCtx->cfg_ini;
426
427 if (NULL == cfg_param)
428 {
429 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
430 "cfg_params not available !!");
431 return ;
432 }
433
434 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
435
436 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
437 {
438 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
439 (eCSR_DOT11_MODE_11ac == phyMode) ||
440 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
441 {
442 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
443 "Setting phymode to 11n!!");
444 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
445 }
446 }
447 else
448 {
449 /*New country Supports 11ac as well resetting value back from .ini*/
450 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
451 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
452 return ;
453 }
454
455 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
456 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
457 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
458 {
459 VOS_STATUS vosStatus;
460
461 // need to issue a disconnect to CSR.
462 INIT_COMPLETION(pAdapter->disconnect_comp_var);
463 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
464 pAdapter->sessionId,
465 eCSR_DISCONNECT_REASON_UNSPECIFIED );
466
467 if (VOS_STATUS_SUCCESS == vosStatus)
468 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
469 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
470
471 }
472}
473
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700474void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
475{
476 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
477 hdd_config_t *cfg_param;
478
479 if (NULL == pHddCtx)
480 {
481 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
482 "HDD Context is null !!");
483 return ;
484 }
485
486 cfg_param = pHddCtx->cfg_ini;
487
488 if (NULL == cfg_param)
489 {
490 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
491 "cfg_params not available !!");
492 return ;
493 }
494
495 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
496 {
497 /*New country doesn't support DFS */
498 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
499 }
500 else
501 {
502 /*New country Supports DFS as well resetting value back from .ini*/
503 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
504 }
505
506}
507
Jeff Johnson295189b2012-06-20 16:38:30 -0700508int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
509{
510 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
511 hdd_priv_data_t priv_data;
512 tANI_U8 *command = NULL;
513 int ret = 0;
514
515 if (NULL == pAdapter)
516 {
517 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700518 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700519 ret = -ENODEV;
520 goto exit;
521 }
522
Jeff Johnsone7245742012-09-05 17:12:55 -0700523 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700524 {
525 ret = -EINVAL;
526 goto exit;
527 }
528
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -0700529 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
530 {
531 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
532 "%s:LOGP in Progress. Ignore!!!", __func__);
533 ret = -EBUSY;
534 goto exit;
535 }
536
Jeff Johnson295189b2012-06-20 16:38:30 -0700537 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
538 {
539 ret = -EFAULT;
540 goto exit;
541 }
542
543 command = kmalloc(priv_data.total_len, GFP_KERNEL);
544 if (!command)
545 {
546 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700547 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700548 ret = -ENOMEM;
549 goto exit;
550 }
551
552 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
553 {
554 ret = -EFAULT;
555 goto exit;
556 }
557
558 if ((SIOCDEVPRIVATE + 1) == cmd)
559 {
560 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
561
562 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700563 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700564
565 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
566 {
567 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
568 sizeof(tSirMacAddr)))
569 {
570 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700571 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700572 ret = -EFAULT;
573 }
574 }
Amar Singhal0974e402013-02-12 14:27:46 -0800575 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700576 {
Amar Singhal0974e402013-02-12 14:27:46 -0800577 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700578 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800579
Jeff Johnson295189b2012-06-20 16:38:30 -0700580 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800581
582 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700583 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700584 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800585 "%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 -0700586 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800587 ret = hdd_setBand_helper(dev, ptr);
588 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700589 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
590 {
591 char *country_code;
592
593 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700594
595 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkalad86a14e2013-04-18 16:41:54 +0530596 hdd_checkandupdate_phymode(pAdapter, country_code);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700597 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
598 pAdapter, pHddCtx->pvosContext);
599 if( 0 != ret )
600 {
601 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
602 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
603
604 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700605 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800606#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
607 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
608 {
609 tANI_U8 *value = command;
610 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
611 tANI_U8 revision = 0;
612 eHalStatus status = eHAL_STATUS_SUCCESS;
613 v_REGDOMAIN_t regId;
614
615 status = hdd_parse_countryrev(value, countryCode, &revision);
616 if (eHAL_STATUS_SUCCESS != status)
617 {
618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
619 "%s: Failed to parse country revision information", __func__);
620 ret = -EINVAL;
621 goto exit;
622 }
623
624 /* Validate country code */
625 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
626 if (eHAL_STATUS_SUCCESS != status)
627 {
628 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
629 "%s: Invalid country code %s", __func__, countryCode);
630 ret = -EINVAL;
631 goto exit;
632 }
633
634 /* Validate revision */
635 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
636 {
637 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
638 "%s: Invalid revision %d", __func__, revision);
639 ret = -EINVAL;
640 goto exit;
641 }
642
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700643 hdd_checkandupdate_dfssetting(pAdapter, countryCode);
Gopichand Nakkalad86a14e2013-04-18 16:41:54 +0530644 hdd_checkandupdate_phymode(pAdapter, countryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800645 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
646 pAdapter, pHddCtx->pvosContext);
647 if (0 != ret)
648 {
649 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
650 "%s: SME Change Country code fail ret=%d", __func__, ret);
651 ret = -EINVAL;
652 goto exit;
653 }
654
655 if (0 == strncmp(countryCode, "KR", 2))
656 {
657 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
658 revision);
659 if (eHAL_STATUS_SUCCESS != status)
660 {
661 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
662 "%s: Failed to build valid channel list", __func__);
663 ret = -EINVAL;
664 goto exit;
665 }
666 }
667 }
668#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700669 /*
670 command should be a string having format
671 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
672 */
Amar Singhal0974e402013-02-12 14:27:46 -0800673 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700674 {
Amar Singhal0974e402013-02-12 14:27:46 -0800675 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700676
677 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700678 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700679
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800680 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700681 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800682 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
683 {
684 int suspend = 0;
685 tANI_U8 *ptr = (tANI_U8*)command + 15;
686
687 suspend = *ptr - '0';
688 hdd_set_wlan_suspend_mode(suspend);
689 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800690#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
691 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
692 {
693 tANI_U8 *value = command;
694 int rssi = 0;
695 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
696 eHalStatus status = eHAL_STATUS_SUCCESS;
697
698 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
699 value = value + 15;
700
701 sscanf(value, "%d", &rssi);
702 lookUpThreshold = abs(rssi);
703 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
704 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
705 {
706 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
707 "Neighbor lookup threshold value %d is out of range"
708 " (Min: %d Max: %d)", lookUpThreshold,
709 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
710 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
711 ret = -EINVAL;
712 goto exit;
713 }
714
715 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
716 "%s: Received Command to Set Roam trigger"
717 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
718
719 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
720 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
721 if (eHAL_STATUS_SUCCESS != status)
722 {
723 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
724 "%s: Failed to set roam trigger, try again", __func__);
725 ret = -EPERM;
726 goto exit;
727 }
728
729 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
730 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
731 }
732 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
733 {
734 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
735 int rssi = (-1) * lookUpThreshold;
736 char extra[32];
737 tANI_U8 len = 0;
738
739 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
740 if (copy_to_user(priv_data.buf, &extra, len + 1))
741 {
742 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
743 "%s: failed to copy data to user buffer", __func__);
744 ret = -EFAULT;
745 goto exit;
746 }
747 }
748 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
749 {
750 tANI_U8 *value = command;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700751 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800752 /* input refresh period is in terms of seconds */
753 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
754 value = value + 18;
755 /* Convert the value from ascii to integer */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700756 ret = kstrtou16(value, 10, &neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800757 if (ret < 0)
758 {
759 /* If the input value is greater than max value of datatype, then also
760 kstrtou16 fails */
761 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
762 "%s: kstrtou16 failed ",
763 "Input value may be out of range[%d - %d]",
764 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700765 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
766 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800767 ret = -EINVAL;
768 goto exit;
769 }
770
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700771 neighborEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod * 1000;
772 if ((neighborEmptyScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
773 (neighborEmptyScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800774 {
775 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700776 "Neighbor empty scan results refresh period value %d is out of range"
777 " (Min: %d Max: %d)", neighborEmptyScanRefreshPeriod/1000,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700778 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
779 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800780 ret = -EINVAL;
781 goto exit;
782 }
783
784 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
785 "%s: Received Command to Set roam scan period"
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700786 " (Empty Scan refresh period) = %d", __func__, neighborEmptyScanRefreshPeriod/1000);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800787
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700788 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
789 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800790 }
791 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
792 {
793 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
794 char extra[32];
795 tANI_U8 len = 0;
796
797 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
798 /* Returned value is in units of seconds */
799 if (copy_to_user(priv_data.buf, &extra, len + 1))
800 {
801 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
802 "%s: failed to copy data to user buffer", __func__);
803 ret = -EFAULT;
804 goto exit;
805 }
806 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700807 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
808 {
809 tANI_U8 *value = command;
810 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
811 /* input refresh period is in terms of seconds */
812 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
813 value = value + 25;
814 /* Convert the value from ascii to integer */
815 ret = kstrtou16(value, 10, &neighborScanRefreshPeriod);
816 if (ret < 0)
817 {
818 /* If the input value is greater than max value of datatype, then also
819 kstrtou16 fails */
820 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
821 "%s: kstrtou16 failed ",
822 "Input value may be out of range[%d - %d]",
823 __func__,
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700824 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
825 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700826 ret = -EINVAL;
827 goto exit;
828 }
829
830 neighborScanRefreshPeriod = neighborScanRefreshPeriod * 1000;
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700831 if ((neighborScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
832 (neighborScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700833 {
834 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
835 "Neighbor scan results refresh period value %d is out of range"
836 " (Min: %d Max: %d)", neighborScanRefreshPeriod/1000,
837 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
838 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
839 ret = -EINVAL;
840 goto exit;
841 }
842
843 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
844 "%s: Received Command to Set roam scan refresh period"
845 " (Scan refresh period) = %d", __func__, neighborScanRefreshPeriod/1000);
846
847 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
848 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
849 }
850 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
851 {
852 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
853 char extra[32];
854 tANI_U8 len = 0;
855
856 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
857 /* Returned value is in units of seconds */
858 if (copy_to_user(priv_data.buf, &extra, len + 1))
859 {
860 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
861 "%s: failed to copy data to user buffer", __func__);
862 ret = -EFAULT;
863 goto exit;
864 }
865 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800866#endif
867#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
868 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
869 {
870 tANI_U8 *value = command;
871 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
872
873 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
874 value = value + 13;
875 /* Convert the value from ascii to integer */
876 ret = kstrtou8(value, 10, &roamRssiDiff);
877 if (ret < 0)
878 {
879 /* If the input value is greater than max value of datatype, then also
880 kstrtou8 fails */
881 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
882 "%s: kstrtou8 failed range [%d - %d]", __func__,
883 CFG_ROAM_RSSI_DIFF_MIN,
884 CFG_ROAM_RSSI_DIFF_MAX);
885 ret = -EINVAL;
886 goto exit;
887 }
888
889 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
890 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
891 {
892 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
893 "Roam rssi diff value %d is out of range"
894 " (Min: %d Max: %d)", roamRssiDiff,
895 CFG_ROAM_RSSI_DIFF_MIN,
896 CFG_ROAM_RSSI_DIFF_MAX);
897 ret = -EINVAL;
898 goto exit;
899 }
900
901 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
902 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
903
904 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
905 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
906 }
907 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
908 {
909 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
910 char extra[32];
911 tANI_U8 len = 0;
912
913 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
914 if (copy_to_user(priv_data.buf, &extra, len + 1))
915 {
916 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
917 "%s: failed to copy data to user buffer", __func__);
918 ret = -EFAULT;
919 goto exit;
920 }
921 }
922#endif
923#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
924 else if (strncmp(command, "GETBAND", 7) == 0)
925 {
926 int band = -1;
927 char extra[32];
928 tANI_U8 len = 0;
929 hdd_getBand_helper(pHddCtx, &band);
930
931 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
932 if (copy_to_user(priv_data.buf, &extra, len + 1))
933 {
934 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
935 "%s: failed to copy data to user buffer", __func__);
936 ret = -EFAULT;
937 goto exit;
938 }
939 }
940 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
941 {
942 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
943 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
944 tANI_U8 revision = 0;
945 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
946 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
947 char extra[32] = {0};
948 tANI_U8 len = 0;
949
950 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
951 {
952 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
953 "%s: failed to get country code", __func__);
954 ret = -EFAULT;
955 goto exit;
956 }
957 pBuf[uBufLen] = '\0';
958 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
959
960 if (0 == strncmp(pBuf, "KR", 2))
961 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
962 else
963 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
964
965 if (copy_to_user(priv_data.buf, &extra, len + 1))
966 {
967 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
968 "%s: failed to copy data to user buffer", __func__);
969 ret = -EFAULT;
970 goto exit;
971 }
972 }
973 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
974 {
975 tANI_U8 *value = command;
976 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
977 tANI_U8 numChannels = 0;
978 eHalStatus status = eHAL_STATUS_SUCCESS;
979
980 status = hdd_parse_channellist(value, ChannelList, &numChannels);
981 if (eHAL_STATUS_SUCCESS != status)
982 {
983 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
984 "%s: Failed to parse channel list information", __func__);
985 ret = -EINVAL;
986 goto exit;
987 }
988
989 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
990 {
991 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
992 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
993 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
994 ret = -EINVAL;
995 goto exit;
996 }
997 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
998 numChannels);
999 if (eHAL_STATUS_SUCCESS != status)
1000 {
1001 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1002 "%s: Failed to update channel list information", __func__);
1003 ret = -EINVAL;
1004 goto exit;
1005 }
1006 }
1007 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
1008 {
1009 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1010 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07001011 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001012 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07001013 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001014
1015 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
1016 ChannelList, &numChannels ))
1017 {
1018 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1019 "%s: failed to get roam scan channel list", __func__);
1020 ret = -EFAULT;
1021 goto exit;
1022 }
1023 /* output channel list is of the format
1024 [Number of roam scan channels][Channel1][Channel2]... */
1025 /* copy the number of channels in the 0th index */
1026 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
1027 for (j = 0; (j < numChannels); j++)
1028 {
1029 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
1030 }
1031
1032 if (copy_to_user(priv_data.buf, &extra, len + 1))
1033 {
1034 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1035 "%s: failed to copy data to user buffer", __func__);
1036 ret = -EFAULT;
1037 goto exit;
1038 }
1039 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001040 else if (strncmp(command, "GETCCXMODE", 10) == 0)
1041 {
1042 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1043 char extra[32];
1044 tANI_U8 len = 0;
1045
1046 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
1047 if (copy_to_user(priv_data.buf, &extra, len + 1))
1048 {
1049 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1050 "%s: failed to copy data to user buffer", __func__);
1051 ret = -EFAULT;
1052 goto exit;
1053 }
1054 }
1055 else if (strncmp(command, "GETOKCMODE", 10) == 0)
1056 {
1057 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
1058 char extra[32];
1059 tANI_U8 len = 0;
1060
1061 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
1062 if (copy_to_user(priv_data.buf, &extra, len + 1))
1063 {
1064 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1065 "%s: failed to copy data to user buffer", __func__);
1066 ret = -EFAULT;
1067 goto exit;
1068 }
1069 }
1070 else if (strncmp(command, "GETFASTROAM", 10) == 0)
1071 {
1072 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1073 char extra[32];
1074 tANI_U8 len = 0;
1075
1076 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
1077 if (copy_to_user(priv_data.buf, &extra, len + 1))
1078 {
1079 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1080 "%s: failed to copy data to user buffer", __func__);
1081 ret = -EFAULT;
1082 goto exit;
1083 }
1084 }
1085 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
1086 {
1087 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1088 char extra[32];
1089 tANI_U8 len = 0;
1090
1091 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
1092 if (copy_to_user(priv_data.buf, &extra, len + 1))
1093 {
1094 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1095 "%s: failed to copy data to user buffer", __func__);
1096 ret = -EFAULT;
1097 goto exit;
1098 }
1099 }
1100 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
1101 {
1102 tANI_U8 *value = command;
1103 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1104
1105 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1106 value = value + 26;
1107 /* Convert the value from ascii to integer */
1108 ret = kstrtou8(value, 10, &minTime);
1109 if (ret < 0)
1110 {
1111 /* If the input value is greater than max value of datatype, then also
1112 kstrtou8 fails */
1113 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1114 "%s: kstrtou8 failed range [%d - %d]", __func__,
1115 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1116 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1117 ret = -EINVAL;
1118 goto exit;
1119 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001120 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1121 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1122 {
1123 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1124 "scan min channel time value %d is out of range"
1125 " (Min: %d Max: %d)", minTime,
1126 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1127 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1128 ret = -EINVAL;
1129 goto exit;
1130 }
1131
1132 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1133 "%s: Received Command to change channel min time = %d", __func__, minTime);
1134
1135 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1136 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1137 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001138 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1139 {
1140 tANI_U8 *value = command;
1141 tANI_U8 channel = 0;
1142 tANI_U8 dwellTime = 0;
1143 tANI_U8 bufLen = 0;
1144 tANI_U8 *buf = NULL;
1145 tSirMacAddr targetApBssid;
1146 eHalStatus status = eHAL_STATUS_SUCCESS;
1147 struct ieee80211_channel chan;
1148 tANI_U8 finalLen = 0;
1149 tANI_U8 *finalBuf = NULL;
1150 tANI_U8 temp = 0;
1151 u64 cookie;
1152 hdd_station_ctx_t *pHddStaCtx = NULL;
1153 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1154
1155 /* if not associated, no need to send action frame */
1156 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1157 {
1158 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1159 ret = -EINVAL;
1160 goto exit;
1161 }
1162
1163 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1164 &dwellTime, &buf, &bufLen);
1165 if (eHAL_STATUS_SUCCESS != status)
1166 {
1167 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1168 "%s: Failed to parse send action frame data", __func__);
1169 ret = -EINVAL;
1170 goto exit;
1171 }
1172
1173 /* if the target bssid is different from currently associated AP,
1174 then no need to send action frame */
1175 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1176 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1177 {
1178 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1179 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001180 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001181 goto exit;
1182 }
1183
1184 /* if the channel number is different from operating channel then
1185 no need to send action frame */
1186 if (channel != pHddStaCtx->conn_info.operationChannel)
1187 {
1188 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1189 "%s: channel(%d) is different from operating channel(%d)",
1190 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1191 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001192 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001193 goto exit;
1194 }
1195 chan.center_freq = sme_ChnToFreq(channel);
1196
1197 finalLen = bufLen + 24;
1198 finalBuf = vos_mem_malloc(finalLen);
1199 if (NULL == finalBuf)
1200 {
1201 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1202 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001203 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001204 goto exit;
1205 }
1206 vos_mem_zero(finalBuf, finalLen);
1207
1208 /* Fill subtype */
1209 temp = SIR_MAC_MGMT_ACTION << 4;
1210 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1211
1212 /* Fill type */
1213 temp = SIR_MAC_MGMT_FRAME;
1214 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1215
1216 /* Fill destination address (bssid of the AP) */
1217 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1218
1219 /* Fill BSSID (STA mac address) */
1220 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1221
1222 /* Fill source address (STA mac address) */
1223 vos_mem_copy(finalBuf + 16, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1224
1225 /* Fill received buffer from 24th address */
1226 vos_mem_copy(finalBuf + 24, buf, bufLen);
1227
Jeff Johnson11c33152013-04-16 17:52:40 -07001228 /* done with the parsed buffer */
1229 vos_mem_free(buf);
1230
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001231 wlan_hdd_action( NULL, dev, &chan, 0, NL80211_CHAN_HT20,
1232 1, dwellTime, finalBuf, finalLen, 1,
1233 1, &cookie );
1234 vos_mem_free(finalBuf);
1235 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001236 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1237 {
1238 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1239 char extra[32];
1240 tANI_U8 len = 0;
1241
1242 /* value is interms of msec */
1243 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1244 if (copy_to_user(priv_data.buf, &extra, len + 1))
1245 {
1246 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1247 "%s: failed to copy data to user buffer", __func__);
1248 ret = -EFAULT;
1249 goto exit;
1250 }
1251 }
1252 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1253 {
1254 tANI_U8 *value = command;
1255 tANI_U8 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
1256
1257 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1258 value = value + 19;
1259 /* Convert the value from ascii to integer */
1260 ret = kstrtou8(value, 10, &maxTime);
1261 if (ret < 0)
1262 {
1263 /* If the input value is greater than max value of datatype, then also
1264 kstrtou8 fails */
1265 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1266 "%s: kstrtou8 failed range [%d - %d]", __func__,
1267 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1268 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1269 ret = -EINVAL;
1270 goto exit;
1271 }
1272
1273 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1274 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1275 {
1276 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1277 "lfr mode value %d is out of range"
1278 " (Min: %d Max: %d)", maxTime,
1279 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1280 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1281 ret = -EINVAL;
1282 goto exit;
1283 }
1284
1285 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1286 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1287
1288 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
1289 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1290 }
1291 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1292 {
1293 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1294 char extra[32];
1295 tANI_U8 len = 0;
1296
1297 /* value is interms of msec */
1298 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1299 if (copy_to_user(priv_data.buf, &extra, len + 1))
1300 {
1301 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1302 "%s: failed to copy data to user buffer", __func__);
1303 ret = -EFAULT;
1304 goto exit;
1305 }
1306 }
1307 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1308 {
1309 tANI_U8 *value = command;
1310 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1311
1312 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1313 value = value + 16;
1314 /* Convert the value from ascii to integer */
1315 ret = kstrtou16(value, 10, &val);
1316 if (ret < 0)
1317 {
1318 /* If the input value is greater than max value of datatype, then also
1319 kstrtou16 fails */
1320 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1321 "%s: kstrtou16 failed range [%d - %d]", __func__,
1322 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1323 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1324 ret = -EINVAL;
1325 goto exit;
1326 }
1327
1328 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1329 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1330 {
1331 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1332 "scan home time value %d is out of range"
1333 " (Min: %d Max: %d)", val,
1334 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1335 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1336 ret = -EINVAL;
1337 goto exit;
1338 }
1339
1340 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1341 "%s: Received Command to change scan home time = %d", __func__, val);
1342
1343 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1344 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1345 }
1346 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1347 {
1348 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1349 char extra[32];
1350 tANI_U8 len = 0;
1351
1352 /* value is interms of msec */
1353 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1354 if (copy_to_user(priv_data.buf, &extra, len + 1))
1355 {
1356 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1357 "%s: failed to copy data to user buffer", __func__);
1358 ret = -EFAULT;
1359 goto exit;
1360 }
1361 }
1362 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1363 {
1364 tANI_U8 *value = command;
1365 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1366
1367 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1368 value = value + 17;
1369 /* Convert the value from ascii to integer */
1370 ret = kstrtou8(value, 10, &val);
1371 if (ret < 0)
1372 {
1373 /* If the input value is greater than max value of datatype, then also
1374 kstrtou8 fails */
1375 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1376 "%s: kstrtou8 failed range [%d - %d]", __func__,
1377 CFG_ROAM_INTRA_BAND_MIN,
1378 CFG_ROAM_INTRA_BAND_MAX);
1379 ret = -EINVAL;
1380 goto exit;
1381 }
1382
1383 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1384 (val > CFG_ROAM_INTRA_BAND_MAX))
1385 {
1386 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1387 "intra band mode value %d is out of range"
1388 " (Min: %d Max: %d)", val,
1389 CFG_ROAM_INTRA_BAND_MIN,
1390 CFG_ROAM_INTRA_BAND_MAX);
1391 ret = -EINVAL;
1392 goto exit;
1393 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001394 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1395 "%s: Received Command to change intra band = %d", __func__, val);
1396
1397 pHddCtx->cfg_ini->nRoamIntraBand = val;
1398 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1399 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001400 else if (strncmp(command, "SETWESMODE", 10) == 0)
1401 {
1402 tANI_U8 *value = command;
1403 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
1404
1405 /* Move pointer to ahead of SETWESMODE<delimiter> */
1406 value = value + 11;
1407 /* Convert the value from ascii to integer */
1408 ret = kstrtou8(value, 10, &wesMode);
1409 if (ret < 0)
1410 {
1411 /* If the input value is greater than max value of datatype, then also
1412 kstrtou8 fails */
1413 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1414 "%s: kstrtou8 failed range [%d - %d]", __func__,
1415 CFG_ENABLE_WES_MODE_NAME_MIN,
1416 CFG_ENABLE_WES_MODE_NAME_MAX);
1417 ret = -EINVAL;
1418 goto exit;
1419 }
1420
1421 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
1422 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
1423 {
1424 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1425 "WES Mode value %d is out of range"
1426 " (Min: %d Max: %d)", wesMode,
1427 CFG_ENABLE_WES_MODE_NAME_MIN,
1428 CFG_ENABLE_WES_MODE_NAME_MAX);
1429 ret = -EINVAL;
1430 goto exit;
1431 }
1432 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1433 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
1434
1435 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
1436 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
1437 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001438 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1439 {
1440 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1441 char extra[32];
1442 tANI_U8 len = 0;
1443
1444 /* value is interms of msec */
1445 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1446 if (copy_to_user(priv_data.buf, &extra, len + 1))
1447 {
1448 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1449 "%s: failed to copy data to user buffer", __func__);
1450 ret = -EFAULT;
1451 goto exit;
1452 }
1453 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001454 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
1455 {
1456 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
1457 char extra[32];
1458 tANI_U8 len = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001459
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001460 len = snprintf(extra, sizeof(extra), "%s %d", command, wesMode);
1461 if (copy_to_user(priv_data.buf, &extra, len + 1))
1462 {
1463 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1464 "%s: failed to copy data to user buffer", __func__);
1465 ret = -EFAULT;
1466 goto exit;
1467 }
1468 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001469#endif
1470#ifdef FEATURE_WLAN_LFR
1471 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1472 {
1473 tANI_U8 *value = command;
1474 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1475
1476 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1477 value = value + 12;
1478 /* Convert the value from ascii to integer */
1479 ret = kstrtou8(value, 10, &lfrMode);
1480 if (ret < 0)
1481 {
1482 /* If the input value is greater than max value of datatype, then also
1483 kstrtou8 fails */
1484 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1485 "%s: kstrtou8 failed range [%d - %d]", __func__,
1486 CFG_LFR_FEATURE_ENABLED_MIN,
1487 CFG_LFR_FEATURE_ENABLED_MAX);
1488 ret = -EINVAL;
1489 goto exit;
1490 }
1491
1492 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1493 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1494 {
1495 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1496 "lfr mode value %d is out of range"
1497 " (Min: %d Max: %d)", lfrMode,
1498 CFG_LFR_FEATURE_ENABLED_MIN,
1499 CFG_LFR_FEATURE_ENABLED_MAX);
1500 ret = -EINVAL;
1501 goto exit;
1502 }
1503
1504 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1505 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1506
1507 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1508 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1509 }
1510#endif
1511#ifdef WLAN_FEATURE_VOWIFI_11R
1512 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1513 {
1514 tANI_U8 *value = command;
1515 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1516
1517 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1518 value = value + 18;
1519 /* Convert the value from ascii to integer */
1520 ret = kstrtou8(value, 10, &ft);
1521 if (ret < 0)
1522 {
1523 /* If the input value is greater than max value of datatype, then also
1524 kstrtou8 fails */
1525 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1526 "%s: kstrtou8 failed range [%d - %d]", __func__,
1527 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1528 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1529 ret = -EINVAL;
1530 goto exit;
1531 }
1532
1533 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1534 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1535 {
1536 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1537 "ft mode value %d is out of range"
1538 " (Min: %d Max: %d)", ft,
1539 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1540 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1541 ret = -EINVAL;
1542 goto exit;
1543 }
1544
1545 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1546 "%s: Received Command to change ft mode = %d", __func__, ft);
1547
1548 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1549 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1550 }
1551#endif
1552#ifdef FEATURE_WLAN_CCX
1553 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1554 {
1555 tANI_U8 *value = command;
1556 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1557
1558 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1559 value = value + 11;
1560 /* Convert the value from ascii to integer */
1561 ret = kstrtou8(value, 10, &ccxMode);
1562 if (ret < 0)
1563 {
1564 /* If the input value is greater than max value of datatype, then also
1565 kstrtou8 fails */
1566 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1567 "%s: kstrtou8 failed range [%d - %d]", __func__,
1568 CFG_CCX_FEATURE_ENABLED_MIN,
1569 CFG_CCX_FEATURE_ENABLED_MAX);
1570 ret = -EINVAL;
1571 goto exit;
1572 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001573 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1574 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1575 {
1576 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1577 "Ccx mode value %d is out of range"
1578 " (Min: %d Max: %d)", ccxMode,
1579 CFG_CCX_FEATURE_ENABLED_MIN,
1580 CFG_CCX_FEATURE_ENABLED_MAX);
1581 ret = -EINVAL;
1582 goto exit;
1583 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001584 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1585 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1586
1587 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1588 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1589 }
1590#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001591 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1592 {
1593 tANI_U8 *value = command;
1594 tANI_BOOLEAN roamScanControl = 0;
1595
1596 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1597 value = value + 19;
1598 /* Convert the value from ascii to integer */
1599 ret = kstrtou8(value, 10, &roamScanControl);
1600 if (ret < 0)
1601 {
1602 /* If the input value is greater than max value of datatype, then also
1603 kstrtou8 fails */
1604 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1605 "%s: kstrtou8 failed ", __func__);
1606 ret = -EINVAL;
1607 goto exit;
1608 }
1609
1610 if (0 != roamScanControl)
1611 {
1612 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1613 "roam scan control invalid value = %d",
1614 roamScanControl);
1615 ret = -EINVAL;
1616 goto exit;
1617 }
1618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1619 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1620
1621 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1622 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001623#ifdef FEATURE_WLAN_OKC
1624 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1625 {
1626 tANI_U8 *value = command;
1627 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1628
1629 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1630 value = value + 11;
1631 /* Convert the value from ascii to integer */
1632 ret = kstrtou8(value, 10, &okcMode);
1633 if (ret < 0)
1634 {
1635 /* If the input value is greater than max value of datatype, then also
1636 kstrtou8 fails */
1637 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1638 "%s: kstrtou8 failed range [%d - %d]", __func__,
1639 CFG_OKC_FEATURE_ENABLED_MIN,
1640 CFG_OKC_FEATURE_ENABLED_MAX);
1641 ret = -EINVAL;
1642 goto exit;
1643 }
1644
1645 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1646 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1647 {
1648 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1649 "Okc mode value %d is out of range"
1650 " (Min: %d Max: %d)", okcMode,
1651 CFG_OKC_FEATURE_ENABLED_MIN,
1652 CFG_OKC_FEATURE_ENABLED_MAX);
1653 ret = -EINVAL;
1654 goto exit;
1655 }
1656
1657 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1658 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1659
1660 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1661 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001662 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1663 {
1664 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1665 char extra[32];
1666 tANI_U8 len = 0;
1667
1668 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1669 if (copy_to_user(priv_data.buf, &extra, len + 1))
1670 {
1671 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1672 "%s: failed to copy data to user buffer", __func__);
1673 ret = -EFAULT;
1674 goto exit;
1675 }
1676 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001677#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001678 else {
1679 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
1680 __func__, command);
1681 }
1682
Jeff Johnson295189b2012-06-20 16:38:30 -07001683 }
1684exit:
1685 if (command)
1686 {
1687 kfree(command);
1688 }
1689 return ret;
1690}
1691
Srinivas Girigowdade697412013-02-14 16:31:48 -08001692#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1693void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
1694{
1695 eCsrBand band = -1;
1696 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
1697 switch (band)
1698 {
1699 case eCSR_BAND_ALL:
1700 *pBand = WLAN_HDD_UI_BAND_AUTO;
1701 break;
1702
1703 case eCSR_BAND_24:
1704 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
1705 break;
1706
1707 case eCSR_BAND_5G:
1708 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
1709 break;
1710
1711 default:
1712 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
1713 *pBand = -1;
1714 break;
1715 }
1716}
1717
1718/**---------------------------------------------------------------------------
1719
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001720 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
1721
1722 This function parses the send action frame data passed in the format
1723 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
1724
1725 \param - pValue Pointer to input country code revision
1726 \param - pTargetApBssid Pointer to target Ap bssid
1727 \param - pChannel Pointer to the Target AP channel
1728 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
1729 \param - pBuf Pointer to data
1730 \param - pBufLen Pointer to data length
1731
1732 \return - 0 for success non-zero for failure
1733
1734 --------------------------------------------------------------------------*/
1735VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
1736 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
1737{
1738 tANI_U8 *inPtr = pValue;
1739 tANI_U8 *dataEnd;
1740 int tempInt;
1741 int j = 0;
1742 int i = 0;
1743 int v = 0;
1744 tANI_U8 tempBuf[32];
1745 tANI_U8 tempByte = 0;
1746
1747 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1748 /*no argument after the command*/
1749 if (NULL == inPtr)
1750 {
1751 return -EINVAL;
1752 }
1753
1754 /*no space after the command*/
1755 else if (SPACE_ASCII_VALUE != *inPtr)
1756 {
1757 return -EINVAL;
1758 }
1759
1760 /*removing empty spaces*/
1761 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1762
1763 /*no argument followed by spaces*/
1764 if ('\0' == *inPtr)
1765 {
1766 return -EINVAL;
1767 }
1768
1769 /*getting the first argument ie the target AP bssid */
1770 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
1771 {
1772 return -EINVAL;
1773 }
1774 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
1775 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
1776 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
1777
1778 /* point to the next argument */
1779 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1780 /*no argument after the command*/
1781 if (NULL == inPtr) return -EINVAL;
1782
1783 /*removing empty spaces*/
1784 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1785
1786 /*no argument followed by spaces*/
1787 if ('\0' == *inPtr)
1788 {
1789 return -EINVAL;
1790 }
1791
1792 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07001793 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001794 v = kstrtos32(tempBuf, 10, &tempInt);
1795 if ( v < 0) return -EINVAL;
1796
1797 *pChannel = tempInt;
1798
1799 /* point to the next argument */
1800 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1801 /*no argument after the command*/
1802 if (NULL == inPtr) return -EINVAL;
1803 /*removing empty spaces*/
1804 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1805
1806 /*no argument followed by spaces*/
1807 if ('\0' == *inPtr)
1808 {
1809 return -EINVAL;
1810 }
1811
1812 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07001813 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001814 v = kstrtos32(tempBuf, 10, &tempInt);
1815 if ( v < 0) return -EINVAL;
1816
1817 *pDwellTime = tempInt;
1818
1819 /* point to the next argument */
1820 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1821 /*no argument after the command*/
1822 if (NULL == inPtr) return -EINVAL;
1823 /*removing empty spaces*/
1824 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1825
1826 /*no argument followed by spaces*/
1827 if ('\0' == *inPtr)
1828 {
1829 return -EINVAL;
1830 }
1831
1832 /* find the length of data */
1833 dataEnd = inPtr;
1834 while(('\0' != *dataEnd) )
1835 {
1836 dataEnd++;
1837 ++(*pBufLen);
1838 }
1839 if ( *pBufLen <= 0) return -EINVAL;
1840
1841 *pBuf = vos_mem_malloc(sizeof(*pBufLen));
1842 if (NULL == *pBuf)
1843 {
1844 hddLog(VOS_TRACE_LEVEL_FATAL,
1845 "%s: vos_mem_alloc failed ", __func__);
1846 return -EINVAL;
1847 }
1848
1849 /* the buffer received from the upper layer is character buffer,
1850 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
1851 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
1852 and f0 in 3rd location */
1853 for (i = 0, j = 0; j < *pBufLen; j += 2)
1854 {
1855 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
1856 (*pBuf)[i++] = tempByte;
1857 }
1858 *pBufLen = i;
1859 return VOS_STATUS_SUCCESS;
1860}
1861
1862#endif
1863/**---------------------------------------------------------------------------
1864
Srinivas Girigowdade697412013-02-14 16:31:48 -08001865 \brief hdd_parse_countryrev() - HDD Parse country code revision
1866
1867 This function parses the country code revision passed in the format
1868 SETCOUNTRYREV<space><Country code><space>revision
1869
1870 \param - pValue Pointer to input country code revision
1871 \param - pCountryCode Pointer to local output array to record country code
1872 \param - pRevision Pointer to store revision integer number
1873
1874 \return - 0 for success non-zero for failure
1875
1876 --------------------------------------------------------------------------*/
1877VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
1878{
1879 tANI_U8 *inPtr = pValue;
1880 int tempInt;
1881
1882 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1883 /*no argument after the command*/
1884 if (NULL == inPtr)
1885 {
1886 return -EINVAL;
1887 }
1888
1889 /*no space after the command*/
1890 else if (SPACE_ASCII_VALUE != *inPtr)
1891 {
1892 return -EINVAL;
1893 }
1894
1895 /*removing empty spaces*/
1896 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
1897
1898 /*no argument followed by spaces*/
1899 if ('\0' == *inPtr)
1900 {
1901 return -EINVAL;
1902 }
1903
1904 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07001905 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001906
1907 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1908 "Country code is : %s", pCountryCode);
1909
1910 /*inPtr pointing to the beginning of first space after country code */
1911 inPtr = strpbrk( inPtr, " " );
1912 /*no revision number after the country code argument */
1913 if (NULL == inPtr)
1914 {
1915 return -EINVAL;
1916 }
1917
1918 inPtr++;
1919
1920 /*removing empty space*/
1921 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1922
1923 /*no channel list after the number of channels argument and spaces*/
1924 if (0 == strncmp(pCountryCode, "KR", 2))
1925 {
1926 if ('\0' == *inPtr)
1927 {
1928 return -EINVAL;
1929 }
1930
1931 sscanf(inPtr, "%d", &tempInt);
1932 *pRevision = tempInt;
1933 }
1934 else
1935 {
1936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1937 "Revision input is required only for Country KR");
1938 return -EINVAL;
1939 }
1940 return VOS_STATUS_SUCCESS;
1941}
1942
1943/**---------------------------------------------------------------------------
1944
1945 \brief hdd_parse_channellist() - HDD Parse channel list
1946
1947 This function parses the channel list passed in the format
1948 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001949 if the Number of channels (N) does not match with the actual number of channels passed
1950 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
1951 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
1952 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
1953 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08001954
1955 \param - pValue Pointer to input channel list
1956 \param - ChannelList Pointer to local output array to record channel list
1957 \param - pNumChannels Pointer to number of roam scan channels
1958
1959 \return - 0 for success non-zero for failure
1960
1961 --------------------------------------------------------------------------*/
1962VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
1963{
1964 tANI_U8 *inPtr = pValue;
1965 int tempInt;
1966 int j = 0;
1967 int v = 0;
1968 char buf[32];
1969
1970 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1971 /*no argument after the command*/
1972 if (NULL == inPtr)
1973 {
1974 return -EINVAL;
1975 }
1976
1977 /*no space after the command*/
1978 else if (SPACE_ASCII_VALUE != *inPtr)
1979 {
1980 return -EINVAL;
1981 }
1982
1983 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001984 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001985
1986 /*no argument followed by spaces*/
1987 if ('\0' == *inPtr)
1988 {
1989 return -EINVAL;
1990 }
1991
1992 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07001993 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001994 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001995 if ((v < 0) ||
1996 (tempInt <= 0) ||
1997 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
1998 {
1999 return -EINVAL;
2000 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002001
2002 *pNumChannels = tempInt;
2003
2004 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2005 "Number of channels are: %d", *pNumChannels);
2006
2007 for (j = 0; j < (*pNumChannels); j++)
2008 {
2009 /*inPtr pointing to the beginning of first space after number of channels*/
2010 inPtr = strpbrk( inPtr, " " );
2011 /*no channel list after the number of channels argument*/
2012 if (NULL == inPtr)
2013 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002014 if (0 != j)
2015 {
2016 *pNumChannels = j;
2017 return VOS_STATUS_SUCCESS;
2018 }
2019 else
2020 {
2021 return -EINVAL;
2022 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002023 }
2024
2025 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002026 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002027
2028 /*no channel list after the number of channels argument and spaces*/
2029 if ( '\0' == *inPtr )
2030 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002031 if (0 != j)
2032 {
2033 *pNumChannels = j;
2034 return VOS_STATUS_SUCCESS;
2035 }
2036 else
2037 {
2038 return -EINVAL;
2039 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002040 }
2041
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002042 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002043 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002044 if ((v < 0) ||
2045 (tempInt <= 0) ||
2046 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2047 {
2048 return -EINVAL;
2049 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002050 pChannelList[j] = tempInt;
2051
2052 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2053 "Channel %d added to preferred channel list",
2054 pChannelList[j] );
2055 }
2056
Srinivas Girigowdade697412013-02-14 16:31:48 -08002057 return VOS_STATUS_SUCCESS;
2058}
2059
Jeff Johnson295189b2012-06-20 16:38:30 -07002060/**---------------------------------------------------------------------------
2061
2062 \brief hdd_open() - HDD Open function
2063
2064 This is called in response to ifconfig up
2065
2066 \param - dev Pointer to net_device structure
2067
2068 \return - 0 for success non-zero for failure
2069
2070 --------------------------------------------------------------------------*/
2071int hdd_open (struct net_device *dev)
2072{
2073 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2074 hdd_context_t *pHddCtx;
2075 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2076 VOS_STATUS status;
2077 v_BOOL_t in_standby = TRUE;
2078
2079 if (NULL == pAdapter)
2080 {
2081 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002082 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002083 return -ENODEV;
2084 }
2085
2086 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2087 if (NULL == pHddCtx)
2088 {
2089 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002090 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002091 return -ENODEV;
2092 }
2093
2094 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2095 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2096 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002097 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2098 {
2099 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302100 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002101 in_standby = FALSE;
2102 break;
2103 }
2104 else
2105 {
2106 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2107 pAdapterNode = pNext;
2108 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002109 }
2110
2111 if (TRUE == in_standby)
2112 {
2113 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2114 {
2115 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2116 "wlan out of power save", __func__);
2117 return -EINVAL;
2118 }
2119 }
2120
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002121 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002122 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2123 {
2124 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002125 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002126 /* Enable TX queues only when we are connected */
2127 netif_tx_start_all_queues(dev);
2128 }
2129
2130 return 0;
2131}
2132
2133int hdd_mon_open (struct net_device *dev)
2134{
2135 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2136
2137 if(pAdapter == NULL) {
2138 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002139 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002140 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002141 }
2142
2143 netif_start_queue(dev);
2144
2145 return 0;
2146}
2147/**---------------------------------------------------------------------------
2148
2149 \brief hdd_stop() - HDD stop function
2150
2151 This is called in response to ifconfig down
2152
2153 \param - dev Pointer to net_device structure
2154
2155 \return - 0 for success non-zero for failure
2156
2157 --------------------------------------------------------------------------*/
2158
2159int hdd_stop (struct net_device *dev)
2160{
2161 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2162 hdd_context_t *pHddCtx;
2163 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2164 VOS_STATUS status;
2165 v_BOOL_t enter_standby = TRUE;
2166
2167 ENTER();
2168
2169 if (NULL == pAdapter)
2170 {
2171 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002172 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002173 return -ENODEV;
2174 }
2175
2176 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2177 if (NULL == pHddCtx)
2178 {
2179 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002180 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002181 return -ENODEV;
2182 }
2183
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002184 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002185 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2186 netif_tx_disable(pAdapter->dev);
2187 netif_carrier_off(pAdapter->dev);
2188
2189
2190 /* SoftAP ifaces should never go in power save mode
2191 making sure same here. */
2192 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2193 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002194 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002195 )
2196 {
2197 /* SoftAP mode, so return from here */
2198 EXIT();
2199 return 0;
2200 }
2201
2202 /* Find if any iface is up then
2203 if any iface is up then can't put device to sleep/ power save mode. */
2204 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2205 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2206 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002207 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2208 {
2209 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302210 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002211 enter_standby = FALSE;
2212 break;
2213 }
2214 else
2215 {
2216 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2217 pAdapterNode = pNext;
2218 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002219 }
2220
2221 if (TRUE == enter_standby)
2222 {
2223 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2224 "entering standby", __func__);
2225 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2226 {
2227 /*log and return success*/
2228 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2229 "wlan in power save", __func__);
2230 }
2231 }
2232
2233 EXIT();
2234 return 0;
2235}
2236
2237/**---------------------------------------------------------------------------
2238
2239 \brief hdd_uninit() - HDD uninit function
2240
2241 This is called during the netdev unregister to uninitialize all data
2242associated with the device
2243
2244 \param - dev Pointer to net_device structure
2245
2246 \return - void
2247
2248 --------------------------------------------------------------------------*/
2249static void hdd_uninit (struct net_device *dev)
2250{
2251 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2252
2253 ENTER();
2254
2255 do
2256 {
2257 if (NULL == pAdapter)
2258 {
2259 hddLog(VOS_TRACE_LEVEL_FATAL,
2260 "%s: NULL pAdapter", __func__);
2261 break;
2262 }
2263
2264 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2265 {
2266 hddLog(VOS_TRACE_LEVEL_FATAL,
2267 "%s: Invalid magic", __func__);
2268 break;
2269 }
2270
2271 if (NULL == pAdapter->pHddCtx)
2272 {
2273 hddLog(VOS_TRACE_LEVEL_FATAL,
2274 "%s: NULL pHddCtx", __func__);
2275 break;
2276 }
2277
2278 if (dev != pAdapter->dev)
2279 {
2280 hddLog(VOS_TRACE_LEVEL_FATAL,
2281 "%s: Invalid device reference", __func__);
2282 /* we haven't validated all cases so let this go for now */
2283 }
2284
2285 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2286
2287 /* after uninit our adapter structure will no longer be valid */
2288 pAdapter->dev = NULL;
2289 pAdapter->magic = 0;
2290 } while (0);
2291
2292 EXIT();
2293}
2294
2295/**---------------------------------------------------------------------------
2296
2297 \brief hdd_release_firmware() -
2298
2299 This function calls the release firmware API to free the firmware buffer.
2300
2301 \param - pFileName Pointer to the File Name.
2302 pCtx - Pointer to the adapter .
2303
2304
2305 \return - 0 for success, non zero for failure
2306
2307 --------------------------------------------------------------------------*/
2308
2309VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2310{
2311 VOS_STATUS status = VOS_STATUS_SUCCESS;
2312 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2313 ENTER();
2314
2315
2316 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2317
2318 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2319
2320 if(pHddCtx->fw) {
2321 release_firmware(pHddCtx->fw);
2322 pHddCtx->fw = NULL;
2323 }
2324 else
2325 status = VOS_STATUS_E_FAILURE;
2326 }
2327 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2328 if(pHddCtx->nv) {
2329 release_firmware(pHddCtx->nv);
2330 pHddCtx->nv = NULL;
2331 }
2332 else
2333 status = VOS_STATUS_E_FAILURE;
2334
2335 }
2336
2337 EXIT();
2338 return status;
2339}
2340
2341/**---------------------------------------------------------------------------
2342
2343 \brief hdd_request_firmware() -
2344
2345 This function reads the firmware file using the request firmware
2346 API and returns the the firmware data and the firmware file size.
2347
2348 \param - pfileName - Pointer to the file name.
2349 - pCtx - Pointer to the adapter .
2350 - ppfw_data - Pointer to the pointer of the firmware data.
2351 - pSize - Pointer to the file size.
2352
2353 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2354
2355 --------------------------------------------------------------------------*/
2356
2357
2358VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2359{
2360 int status;
2361 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2362 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2363 ENTER();
2364
2365 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2366
2367 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2368
2369 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2370 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2371 __func__, pfileName);
2372 retval = VOS_STATUS_E_FAILURE;
2373 }
2374
2375 else {
2376 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2377 *pSize = pHddCtx->fw->size;
2378 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2379 __func__, *pSize);
2380 }
2381 }
2382 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2383
2384 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2385
2386 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2387 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2388 __func__, pfileName);
2389 retval = VOS_STATUS_E_FAILURE;
2390 }
2391
2392 else {
2393 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2394 *pSize = pHddCtx->nv->size;
2395 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2396 __func__, *pSize);
2397 }
2398 }
2399
2400 EXIT();
2401 return retval;
2402}
2403/**---------------------------------------------------------------------------
2404 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2405
2406 This is the function invoked by SME to inform the result of a full power
2407 request issued by HDD
2408
2409 \param - callbackcontext - Pointer to cookie
2410 status - result of request
2411
2412 \return - None
2413
2414--------------------------------------------------------------------------*/
2415void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2416{
2417 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2418
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002419 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002420 if(&pHddCtx->full_pwr_comp_var)
2421 {
2422 complete(&pHddCtx->full_pwr_comp_var);
2423 }
2424}
2425
2426/**---------------------------------------------------------------------------
2427
2428 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2429
2430 This is the function invoked by SME to inform the result of BMPS
2431 request issued by HDD
2432
2433 \param - callbackcontext - Pointer to cookie
2434 status - result of request
2435
2436 \return - None
2437
2438--------------------------------------------------------------------------*/
2439void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2440{
2441
2442 struct completion *completion_var = (struct completion*) callbackContext;
2443
2444 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2445 if(completion_var != NULL)
2446 {
2447 complete(completion_var);
2448 }
2449}
2450
2451/**---------------------------------------------------------------------------
2452
2453 \brief hdd_get_cfg_file_size() -
2454
2455 This function reads the configuration file using the request firmware
2456 API and returns the configuration file size.
2457
2458 \param - pCtx - Pointer to the adapter .
2459 - pFileName - Pointer to the file name.
2460 - pBufSize - Pointer to the buffer size.
2461
2462 \return - 0 for success, non zero for failure
2463
2464 --------------------------------------------------------------------------*/
2465
2466VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2467{
2468 int status;
2469 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2470
2471 ENTER();
2472
2473 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2474
2475 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2476 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2477 status = VOS_STATUS_E_FAILURE;
2478 }
2479 else {
2480 *pBufSize = pHddCtx->fw->size;
2481 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2482 release_firmware(pHddCtx->fw);
2483 pHddCtx->fw = NULL;
2484 }
2485
2486 EXIT();
2487 return VOS_STATUS_SUCCESS;
2488}
2489
2490/**---------------------------------------------------------------------------
2491
2492 \brief hdd_read_cfg_file() -
2493
2494 This function reads the configuration file using the request firmware
2495 API and returns the cfg data and the buffer size of the configuration file.
2496
2497 \param - pCtx - Pointer to the adapter .
2498 - pFileName - Pointer to the file name.
2499 - pBuffer - Pointer to the data buffer.
2500 - pBufSize - Pointer to the buffer size.
2501
2502 \return - 0 for success, non zero for failure
2503
2504 --------------------------------------------------------------------------*/
2505
2506VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2507 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2508{
2509 int status;
2510 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2511
2512 ENTER();
2513
2514 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2515
2516 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2517 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2518 return VOS_STATUS_E_FAILURE;
2519 }
2520 else {
2521 if(*pBufSize != pHddCtx->fw->size) {
2522 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2523 "file size", __func__);
2524 release_firmware(pHddCtx->fw);
2525 pHddCtx->fw = NULL;
2526 return VOS_STATUS_E_FAILURE;
2527 }
2528 else {
2529 if(pBuffer) {
2530 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2531 }
2532 release_firmware(pHddCtx->fw);
2533 pHddCtx->fw = NULL;
2534 }
2535 }
2536
2537 EXIT();
2538
2539 return VOS_STATUS_SUCCESS;
2540}
2541
2542/**---------------------------------------------------------------------------
2543
Jeff Johnson295189b2012-06-20 16:38:30 -07002544 \brief hdd_set_mac_address() -
2545
2546 This function sets the user specified mac address using
2547 the command ifconfig wlanX hw ether <mac adress>.
2548
2549 \param - dev - Pointer to the net device.
2550 - addr - Pointer to the sockaddr.
2551 \return - 0 for success, non zero for failure
2552
2553 --------------------------------------------------------------------------*/
2554
2555static int hdd_set_mac_address(struct net_device *dev, void *addr)
2556{
2557 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2558 struct sockaddr *psta_mac_addr = addr;
2559 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2560
2561 ENTER();
2562
2563 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2564
2565#ifdef HDD_SESSIONIZE
2566 // set the MAC address though the STA ID CFG.
2567 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2568 (v_U8_t *)&pAdapter->macAddressCurrent,
2569 sizeof( pAdapter->macAddressCurrent ),
2570 hdd_set_mac_addr_cb, VOS_FALSE );
2571#endif
2572
2573 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2574
2575 EXIT();
2576 return halStatus;
2577}
2578
2579tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2580{
2581 int i;
2582 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2583 {
2584 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2585 break;
2586 }
2587
2588 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2589 return NULL;
2590
2591 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2592 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2593}
2594
2595void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
2596{
2597 int i;
2598 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2599 {
2600 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
2601 {
2602 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
2603 break;
2604 }
2605 }
2606 return;
2607}
2608
2609#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2610 static struct net_device_ops wlan_drv_ops = {
2611 .ndo_open = hdd_open,
2612 .ndo_stop = hdd_stop,
2613 .ndo_uninit = hdd_uninit,
2614 .ndo_start_xmit = hdd_hard_start_xmit,
2615 .ndo_tx_timeout = hdd_tx_timeout,
2616 .ndo_get_stats = hdd_stats,
2617 .ndo_do_ioctl = hdd_ioctl,
2618 .ndo_set_mac_address = hdd_set_mac_address,
2619 .ndo_select_queue = hdd_select_queue,
2620#ifdef WLAN_FEATURE_PACKET_FILTERING
2621#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
2622 .ndo_set_rx_mode = hdd_set_multicast_list,
2623#else
2624 .ndo_set_multicast_list = hdd_set_multicast_list,
2625#endif //LINUX_VERSION_CODE
2626#endif
2627 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002628 static struct net_device_ops wlan_mon_drv_ops = {
2629 .ndo_open = hdd_mon_open,
2630 .ndo_stop = hdd_stop,
2631 .ndo_uninit = hdd_uninit,
2632 .ndo_start_xmit = hdd_mon_hard_start_xmit,
2633 .ndo_tx_timeout = hdd_tx_timeout,
2634 .ndo_get_stats = hdd_stats,
2635 .ndo_do_ioctl = hdd_ioctl,
2636 .ndo_set_mac_address = hdd_set_mac_address,
2637 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002638
2639#endif
2640
2641void hdd_set_station_ops( struct net_device *pWlanDev )
2642{
2643#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2644 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
2645 pWlanDev->netdev_ops = &wlan_drv_ops;
2646#else
2647 pWlanDev->open = hdd_open;
2648 pWlanDev->stop = hdd_stop;
2649 pWlanDev->uninit = hdd_uninit;
2650 pWlanDev->hard_start_xmit = NULL;
2651 pWlanDev->tx_timeout = hdd_tx_timeout;
2652 pWlanDev->get_stats = hdd_stats;
2653 pWlanDev->do_ioctl = hdd_ioctl;
2654 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
2655 pWlanDev->set_mac_address = hdd_set_mac_address;
2656#endif
2657}
2658
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002659static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07002660{
2661 struct net_device *pWlanDev = NULL;
2662 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002663 /*
2664 * cfg80211 initialization and registration....
2665 */
2666 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
2667
Jeff Johnson295189b2012-06-20 16:38:30 -07002668 if(pWlanDev != NULL)
2669 {
2670
2671 //Save the pointer to the net_device in the HDD adapter
2672 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
2673
Jeff Johnson295189b2012-06-20 16:38:30 -07002674 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
2675
2676 pAdapter->dev = pWlanDev;
2677 pAdapter->pHddCtx = pHddCtx;
2678 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
2679
2680 init_completion(&pAdapter->session_open_comp_var);
2681 init_completion(&pAdapter->session_close_comp_var);
2682 init_completion(&pAdapter->disconnect_comp_var);
2683 init_completion(&pAdapter->linkup_event_var);
2684 init_completion(&pAdapter->cancel_rem_on_chan_var);
2685 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07002686#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2687 init_completion(&pAdapter->offchannel_tx_event);
2688#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002689 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002690#ifdef FEATURE_WLAN_TDLS
2691 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002692 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002693 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002694#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002695 init_completion(&pHddCtx->mc_sus_event_var);
2696 init_completion(&pHddCtx->tx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07002697 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07002698
Jeff Johnson295189b2012-06-20 16:38:30 -07002699 pAdapter->isLinkUpSvcNeeded = FALSE;
2700 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
2701 //Init the net_device structure
2702 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2703
2704 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
2705 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
2706 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
2707 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
2708
2709 hdd_set_station_ops( pAdapter->dev );
2710
2711 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002712 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
2713 pAdapter->wdev.wiphy = pHddCtx->wiphy;
2714 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002715 /* set pWlanDev's parent to underlying device */
2716 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
2717 }
2718
2719 return pAdapter;
2720}
2721
2722VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
2723{
2724 struct net_device *pWlanDev = pAdapter->dev;
2725 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2726 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2727 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2728
2729 if( rtnl_lock_held )
2730 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08002731 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07002732 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
2733 {
2734 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
2735 return VOS_STATUS_E_FAILURE;
2736 }
2737 }
2738 if (register_netdevice(pWlanDev))
2739 {
2740 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
2741 return VOS_STATUS_E_FAILURE;
2742 }
2743 }
2744 else
2745 {
2746 if(register_netdev(pWlanDev))
2747 {
2748 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
2749 return VOS_STATUS_E_FAILURE;
2750 }
2751 }
2752 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
2753
2754 return VOS_STATUS_SUCCESS;
2755}
2756
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002757static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07002758{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002759 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07002760
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002761 if (NULL == pAdapter)
2762 {
2763 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
2764 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07002765 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002766
2767 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2768 {
2769 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
2770 return eHAL_STATUS_NOT_INITIALIZED;
2771 }
2772
2773 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
2774
2775 /* need to make sure all of our scheduled work has completed.
2776 * This callback is called from MC thread context, so it is safe to
2777 * to call below flush workqueue API from here.
2778 */
2779 flush_scheduled_work();
2780
2781 /* We can be blocked while waiting for scheduled work to be
2782 * flushed, and the adapter structure can potentially be freed, in
2783 * which case the magic will have been reset. So make sure the
2784 * magic is still good, and hence the adapter structure is still
2785 * valid, before signaling completion */
2786 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
2787 {
2788 complete(&pAdapter->session_close_comp_var);
2789 }
2790
Jeff Johnson295189b2012-06-20 16:38:30 -07002791 return eHAL_STATUS_SUCCESS;
2792}
2793
2794VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
2795{
2796 struct net_device *pWlanDev = pAdapter->dev;
2797 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2798 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2799 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2800 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2801 int rc = 0;
2802
2803 INIT_COMPLETION(pAdapter->session_open_comp_var);
2804 //Open a SME session for future operation
2805 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
2806 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
2807 if ( !HAL_STATUS_SUCCESS( halStatus ) )
2808 {
2809 hddLog(VOS_TRACE_LEVEL_FATAL,
2810 "sme_OpenSession() failed with status code %08d [x%08lx]",
2811 halStatus, halStatus );
2812 status = VOS_STATUS_E_FAILURE;
2813 goto error_sme_open;
2814 }
2815
2816 //Block on a completion variable. Can't wait forever though.
2817 rc = wait_for_completion_interruptible_timeout(
2818 &pAdapter->session_open_comp_var,
2819 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2820 if (!rc)
2821 {
2822 hddLog(VOS_TRACE_LEVEL_FATAL,
2823 "Session is not opened within timeout period code %08d", rc );
2824 status = VOS_STATUS_E_FAILURE;
2825 goto error_sme_open;
2826 }
2827
2828 // Register wireless extensions
2829 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
2830 {
2831 hddLog(VOS_TRACE_LEVEL_FATAL,
2832 "hdd_register_wext() failed with status code %08d [x%08lx]",
2833 halStatus, halStatus );
2834 status = VOS_STATUS_E_FAILURE;
2835 goto error_register_wext;
2836 }
2837 //Safe to register the hard_start_xmit function again
2838#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2839 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
2840#else
2841 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
2842#endif
2843
2844 //Set the Connection State to Not Connected
2845 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2846
2847 //Set the default operation channel
2848 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
2849
2850 /* Make the default Auth Type as OPEN*/
2851 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2852
2853 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
2854 {
2855 hddLog(VOS_TRACE_LEVEL_FATAL,
2856 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
2857 status, status );
2858 goto error_init_txrx;
2859 }
2860
2861 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2862
2863 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
2864 {
2865 hddLog(VOS_TRACE_LEVEL_FATAL,
2866 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
2867 status, status );
2868 goto error_wmm_init;
2869 }
2870
2871 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2872
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002873#ifdef FEATURE_WLAN_TDLS
2874 if(0 != wlan_hdd_tdls_init(pAdapter))
2875 {
2876 status = VOS_STATUS_E_FAILURE;
2877 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
2878 goto error_tdls_init;
2879 }
2880 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2881#endif
2882
Jeff Johnson295189b2012-06-20 16:38:30 -07002883 return VOS_STATUS_SUCCESS;
2884
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002885#ifdef FEATURE_WLAN_TDLS
2886error_tdls_init:
2887 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2888 hdd_wmm_adapter_close(pAdapter);
2889#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002890error_wmm_init:
2891 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2892 hdd_deinit_tx_rx(pAdapter);
2893error_init_txrx:
2894 hdd_UnregisterWext(pWlanDev);
2895error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002896 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07002897 {
2898 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002899 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002900 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002901 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07002902 {
2903 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002904 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07002905 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002906 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07002907 }
2908}
2909error_sme_open:
2910 return status;
2911}
2912
Jeff Johnson295189b2012-06-20 16:38:30 -07002913void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2914{
2915 hdd_cfg80211_state_t *cfgState;
2916
2917 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
2918
2919 if( NULL != cfgState->buf )
2920 {
2921 int rc;
2922 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
2923 rc = wait_for_completion_interruptible_timeout(
2924 &pAdapter->tx_action_cnf_event,
2925 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2926 if(!rc)
2927 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08002928 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07002929 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
2930 }
2931 }
2932 return;
2933}
Jeff Johnson295189b2012-06-20 16:38:30 -07002934
2935void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2936{
2937 ENTER();
2938 switch ( pAdapter->device_mode )
2939 {
2940 case WLAN_HDD_INFRA_STATION:
2941 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002942 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002943 {
2944 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2945 {
2946 hdd_deinit_tx_rx( pAdapter );
2947 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2948 }
2949
2950 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
2951 {
2952 hdd_wmm_adapter_close( pAdapter );
2953 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2954 }
2955
Jeff Johnson295189b2012-06-20 16:38:30 -07002956 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002957#ifdef FEATURE_WLAN_TDLS
2958 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
2959 {
2960 wlan_hdd_tdls_exit(pAdapter);
2961 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2962 }
2963#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002964
2965 break;
2966 }
2967
2968 case WLAN_HDD_SOFTAP:
2969 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002970 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002971 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002972
2973 hdd_unregister_hostapd(pAdapter);
2974 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07002975 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07002976 break;
2977 }
2978
2979 case WLAN_HDD_MONITOR:
2980 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002981 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07002982 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2983 {
2984 hdd_deinit_tx_rx( pAdapter );
2985 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2986 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002987 if(NULL != pAdapterforTx)
2988 {
2989 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
2990 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002991 break;
2992 }
2993
2994
2995 default:
2996 break;
2997 }
2998
2999 EXIT();
3000}
3001
3002void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3003{
3004 struct net_device *pWlanDev = pAdapter->dev;
3005
3006 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3007 if( rtnl_held )
3008 {
3009 unregister_netdevice(pWlanDev);
3010 }
3011 else
3012 {
3013 unregister_netdev(pWlanDev);
3014 }
3015 // note that the pAdapter is no longer valid at this point
3016 // since the memory has been reclaimed
3017 }
3018
3019}
3020
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003021void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3022{
3023 tSirSetPowerParamsReq powerRequest = { 0 };
3024
3025 powerRequest.uIgnoreDTIM = 1;
3026
3027 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3028 {
3029 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3030 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3031 }
3032 else
3033 {
3034 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3035 }
3036
3037 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3038 *specified during Enter/Exit BMPS when LCD off*/
3039 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3040 NULL, eANI_BOOLEAN_FALSE);
3041 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3042 NULL, eANI_BOOLEAN_FALSE);
3043
3044 /* switch to the DTIM specified in cfg.ini */
3045 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3046 "Switch to DTIM%d", powerRequest.uListenInterval);
3047 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3048
3049}
3050
3051void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3052{
3053 /*Switch back to DTIM 1*/
3054 tSirSetPowerParamsReq powerRequest = { 0 };
3055
3056 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3057 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3058
3059 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3060 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3061 NULL, eANI_BOOLEAN_FALSE);
3062 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3063 NULL, eANI_BOOLEAN_FALSE);
3064
3065 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3066 "Switch to DTIM%d",powerRequest.uListenInterval);
3067 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3068
3069}
3070
Jeff Johnson295189b2012-06-20 16:38:30 -07003071VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3072{
3073 VOS_STATUS status = VOS_STATUS_SUCCESS;
3074
3075 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3076 {
3077 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3078 }
3079
3080 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3081 {
3082 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3083 }
3084
3085 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3086 {
3087 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3088 }
3089
3090 return status;
3091}
3092
3093VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3094{
3095 hdd_adapter_t *pAdapter = NULL;
3096 eHalStatus halStatus;
3097 VOS_STATUS status = VOS_STATUS_E_INVAL;
3098 v_BOOL_t disableBmps = FALSE;
3099 v_BOOL_t disableImps = FALSE;
3100
3101 switch(session_type)
3102 {
3103 case WLAN_HDD_INFRA_STATION:
3104 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003105 case WLAN_HDD_P2P_CLIENT:
3106 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003107 //Exit BMPS -> Is Sta/P2P Client is already connected
3108 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3109 if((NULL != pAdapter)&&
3110 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3111 {
3112 disableBmps = TRUE;
3113 }
3114
3115 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3116 if((NULL != pAdapter)&&
3117 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3118 {
3119 disableBmps = TRUE;
3120 }
3121
3122 //Exit both Bmps and Imps incase of Go/SAP Mode
3123 if((WLAN_HDD_SOFTAP == session_type) ||
3124 (WLAN_HDD_P2P_GO == session_type))
3125 {
3126 disableBmps = TRUE;
3127 disableImps = TRUE;
3128 }
3129
3130 if(TRUE == disableImps)
3131 {
3132 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3133 {
3134 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3135 }
3136 }
3137
3138 if(TRUE == disableBmps)
3139 {
3140 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3141 {
3142 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3143
3144 if(eHAL_STATUS_SUCCESS != halStatus)
3145 {
3146 status = VOS_STATUS_E_FAILURE;
3147 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3148 VOS_ASSERT(0);
3149 return status;
3150 }
3151 }
3152
3153 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3154 {
3155 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3156
3157 if(eHAL_STATUS_SUCCESS != halStatus)
3158 {
3159 status = VOS_STATUS_E_FAILURE;
3160 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3161 VOS_ASSERT(0);
3162 return status;
3163 }
3164 }
3165 }
3166
3167 if((TRUE == disableBmps) ||
3168 (TRUE == disableImps))
3169 {
3170 /* Now, get the chip into Full Power now */
3171 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3172 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3173 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3174
3175 if(halStatus != eHAL_STATUS_SUCCESS)
3176 {
3177 if(halStatus == eHAL_STATUS_PMC_PENDING)
3178 {
3179 //Block on a completion variable. Can't wait forever though
3180 wait_for_completion_interruptible_timeout(
3181 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3182 }
3183 else
3184 {
3185 status = VOS_STATUS_E_FAILURE;
3186 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3187 VOS_ASSERT(0);
3188 return status;
3189 }
3190 }
3191
3192 status = VOS_STATUS_SUCCESS;
3193 }
3194
3195 break;
3196 }
3197 return status;
3198}
3199
3200hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003201 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003202 tANI_U8 rtnl_held )
3203{
3204 hdd_adapter_t *pAdapter = NULL;
3205 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3206 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3207 VOS_STATUS exitbmpsStatus;
3208
3209 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3210
3211 //Disable BMPS incase of Concurrency
3212 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3213
3214 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3215 {
3216 //Fail to Exit BMPS
3217 VOS_ASSERT(0);
3218 return NULL;
3219 }
3220
3221 switch(session_type)
3222 {
3223 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003224 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003225 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003226 {
3227 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3228
3229 if( NULL == pAdapter )
3230 return NULL;
3231
Jeff Johnsone7245742012-09-05 17:12:55 -07003232 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3233 NL80211_IFTYPE_P2P_CLIENT:
3234 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003235
Jeff Johnson295189b2012-06-20 16:38:30 -07003236 pAdapter->device_mode = session_type;
3237
3238 status = hdd_init_station_mode( pAdapter );
3239 if( VOS_STATUS_SUCCESS != status )
3240 goto err_free_netdev;
3241
3242 status = hdd_register_interface( pAdapter, rtnl_held );
3243 if( VOS_STATUS_SUCCESS != status )
3244 {
3245 hdd_deinit_adapter(pHddCtx, pAdapter);
3246 goto err_free_netdev;
3247 }
3248 //Stop the Interface TX queue.
3249 netif_tx_disable(pAdapter->dev);
3250 //netif_tx_disable(pWlanDev);
3251 netif_carrier_off(pAdapter->dev);
3252
3253 break;
3254 }
3255
Jeff Johnson295189b2012-06-20 16:38:30 -07003256 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003257 case WLAN_HDD_SOFTAP:
3258 {
3259 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3260 if( NULL == pAdapter )
3261 return NULL;
3262
Jeff Johnson295189b2012-06-20 16:38:30 -07003263 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3264 NL80211_IFTYPE_AP:
3265 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003266 pAdapter->device_mode = session_type;
3267
3268 status = hdd_init_ap_mode(pAdapter);
3269 if( VOS_STATUS_SUCCESS != status )
3270 goto err_free_netdev;
3271
3272 status = hdd_register_hostapd( pAdapter, rtnl_held );
3273 if( VOS_STATUS_SUCCESS != status )
3274 {
3275 hdd_deinit_adapter(pHddCtx, pAdapter);
3276 goto err_free_netdev;
3277 }
3278
3279 netif_tx_disable(pAdapter->dev);
3280 netif_carrier_off(pAdapter->dev);
3281
3282 hdd_set_conparam( 1 );
3283 break;
3284 }
3285 case WLAN_HDD_MONITOR:
3286 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003287 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3288 if( NULL == pAdapter )
3289 return NULL;
3290
3291 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3292 pAdapter->device_mode = session_type;
3293 status = hdd_register_interface( pAdapter, rtnl_held );
3294#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3295 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3296#else
3297 pAdapter->dev->open = hdd_mon_open;
3298 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3299#endif
3300 hdd_init_tx_rx( pAdapter );
3301 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3302 //Set adapter to be used for data tx. It will use either GO or softap.
3303 pAdapter->sessionCtx.monitor.pAdapterForTx =
3304 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003305 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3306 {
3307 pAdapter->sessionCtx.monitor.pAdapterForTx =
3308 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3309 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003310 /* This workqueue will be used to transmit management packet over
3311 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003312 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3313 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3314 return NULL;
3315 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003316
Jeff Johnson295189b2012-06-20 16:38:30 -07003317 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3318 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003319 }
3320 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003321 case WLAN_HDD_FTM:
3322 {
3323 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3324
3325 if( NULL == pAdapter )
3326 return NULL;
3327 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3328 * message while loading driver in FTM mode. */
3329 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3330 pAdapter->device_mode = session_type;
3331 status = hdd_register_interface( pAdapter, rtnl_held );
3332 }
3333 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003334 default:
3335 {
3336 VOS_ASSERT(0);
3337 return NULL;
3338 }
3339 }
3340
3341
3342 if( VOS_STATUS_SUCCESS == status )
3343 {
3344 //Add it to the hdd's session list.
3345 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3346 if( NULL == pHddAdapterNode )
3347 {
3348 status = VOS_STATUS_E_NOMEM;
3349 }
3350 else
3351 {
3352 pHddAdapterNode->pAdapter = pAdapter;
3353 status = hdd_add_adapter_back ( pHddCtx,
3354 pHddAdapterNode );
3355 }
3356 }
3357
3358 if( VOS_STATUS_SUCCESS != status )
3359 {
3360 if( NULL != pAdapter )
3361 {
3362 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3363 pAdapter = NULL;
3364 }
3365 if( NULL != pHddAdapterNode )
3366 {
3367 vos_mem_free( pHddAdapterNode );
3368 }
3369
3370 goto resume_bmps;
3371 }
3372
3373 if(VOS_STATUS_SUCCESS == status)
3374 {
3375 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3376
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003377 //Initialize the WoWL service
3378 if(!hdd_init_wowl(pAdapter))
3379 {
3380 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3381 goto err_free_netdev;
3382 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003383 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003384 return pAdapter;
3385
3386err_free_netdev:
3387 free_netdev(pAdapter->dev);
3388 wlan_hdd_release_intf_addr( pHddCtx,
3389 pAdapter->macAddressCurrent.bytes );
3390
3391resume_bmps:
3392 //If bmps disabled enable it
3393 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3394 {
3395 hdd_enable_bmps_imps(pHddCtx);
3396 }
3397 return NULL;
3398}
3399
3400VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3401 tANI_U8 rtnl_held )
3402{
3403 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3404 VOS_STATUS status;
3405
3406 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3407 if( VOS_STATUS_SUCCESS != status )
3408 return status;
3409
3410 while ( pCurrent->pAdapter != pAdapter )
3411 {
3412 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3413 if( VOS_STATUS_SUCCESS != status )
3414 break;
3415
3416 pCurrent = pNext;
3417 }
3418 pAdapterNode = pCurrent;
3419 if( VOS_STATUS_SUCCESS == status )
3420 {
3421 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3422 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3423 hdd_remove_adapter( pHddCtx, pAdapterNode );
3424 vos_mem_free( pAdapterNode );
3425
Jeff Johnson295189b2012-06-20 16:38:30 -07003426
3427 /* If there is a single session of STA/P2P client, re-enable BMPS */
3428 if ((!vos_concurrent_sessions_running()) &&
3429 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3430 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3431 {
3432 hdd_enable_bmps_imps(pHddCtx);
3433 }
3434
3435 return VOS_STATUS_SUCCESS;
3436 }
3437
3438 return VOS_STATUS_E_FAILURE;
3439}
3440
3441VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3442{
3443 hdd_adapter_list_node_t *pHddAdapterNode;
3444 VOS_STATUS status;
3445
3446 ENTER();
3447
3448 do
3449 {
3450 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3451 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3452 {
3453 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3454 vos_mem_free( pHddAdapterNode );
3455 }
3456 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3457
3458 EXIT();
3459
3460 return VOS_STATUS_SUCCESS;
3461}
3462
3463void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3464{
3465 v_U8_t addIE[1] = {0};
3466
3467 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3468 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3469 eANI_BOOLEAN_FALSE) )
3470 {
3471 hddLog(LOGE,
3472 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3473 }
3474
3475 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3476 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3477 eANI_BOOLEAN_FALSE) )
3478 {
3479 hddLog(LOGE,
3480 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3481 }
3482
3483 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3484 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3485 eANI_BOOLEAN_FALSE) )
3486 {
3487 hddLog(LOGE,
3488 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3489 }
3490}
3491
3492VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3493{
3494 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3495 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3496 union iwreq_data wrqu;
3497
3498 ENTER();
3499
3500 switch(pAdapter->device_mode)
3501 {
3502 case WLAN_HDD_INFRA_STATION:
3503 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003504 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003505 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3506 {
3507 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3508 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3509 pAdapter->sessionId,
3510 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3511 else
3512 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3513 pAdapter->sessionId,
3514 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3515 //success implies disconnect command got queued up successfully
3516 if(halStatus == eHAL_STATUS_SUCCESS)
3517 {
3518 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3519 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3520 }
3521 memset(&wrqu, '\0', sizeof(wrqu));
3522 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3523 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3524 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3525 }
3526 else
3527 {
3528 hdd_abort_mac_scan(pHddCtx);
3529 }
3530
3531 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3532 {
3533 INIT_COMPLETION(pAdapter->session_close_comp_var);
3534 if (eHAL_STATUS_SUCCESS ==
3535 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3536 hdd_smeCloseSessionCallback, pAdapter))
3537 {
3538 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003539 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003540 &pAdapter->session_close_comp_var,
3541 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3542 }
3543 }
3544
3545 break;
3546
3547 case WLAN_HDD_SOFTAP:
3548 case WLAN_HDD_P2P_GO:
3549 //Any softap specific cleanup here...
3550 mutex_lock(&pHddCtx->sap_lock);
3551 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3552 {
3553 VOS_STATUS status;
3554 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3555
3556 //Stop Bss.
3557 status = WLANSAP_StopBss(pHddCtx->pvosContext);
3558 if (VOS_IS_STATUS_SUCCESS(status))
3559 {
3560 hdd_hostapd_state_t *pHostapdState =
3561 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3562
3563 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
3564
3565 if (!VOS_IS_STATUS_SUCCESS(status))
3566 {
3567 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003568 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003569 }
3570 }
3571 else
3572 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003573 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003574 }
3575 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
3576
3577 if (eHAL_STATUS_FAILURE ==
3578 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
3579 0, NULL, eANI_BOOLEAN_FALSE))
3580 {
3581 hddLog(LOGE,
3582 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003583 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003584 }
3585
3586 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
3587 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
3588 eANI_BOOLEAN_FALSE) )
3589 {
3590 hddLog(LOGE,
3591 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
3592 }
3593
3594 // Reset WNI_CFG_PROBE_RSP Flags
3595 wlan_hdd_reset_prob_rspies(pAdapter);
3596 kfree(pAdapter->sessionCtx.ap.beacon);
3597 pAdapter->sessionCtx.ap.beacon = NULL;
3598 }
3599 mutex_unlock(&pHddCtx->sap_lock);
3600 break;
3601 case WLAN_HDD_MONITOR:
3602 break;
3603 default:
3604 break;
3605 }
3606
3607 EXIT();
3608 return VOS_STATUS_SUCCESS;
3609}
3610
3611VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
3612{
3613 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3614 VOS_STATUS status;
3615 hdd_adapter_t *pAdapter;
3616
3617 ENTER();
3618
3619 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3620
3621 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3622 {
3623 pAdapter = pAdapterNode->pAdapter;
3624 netif_tx_disable(pAdapter->dev);
3625 netif_carrier_off(pAdapter->dev);
3626
3627 hdd_stop_adapter( pHddCtx, pAdapter );
3628
3629 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3630 pAdapterNode = pNext;
3631 }
3632
3633 EXIT();
3634
3635 return VOS_STATUS_SUCCESS;
3636}
3637
3638VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
3639{
3640 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3641 VOS_STATUS status;
3642 hdd_adapter_t *pAdapter;
3643
3644 ENTER();
3645
3646 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3647
3648 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3649 {
3650 pAdapter = pAdapterNode->pAdapter;
3651 netif_tx_disable(pAdapter->dev);
3652 netif_carrier_off(pAdapter->dev);
3653
3654 //Record whether STA is associated
3655 pAdapter->sessionCtx.station.bSendDisconnect =
3656 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
3657 VOS_TRUE : VOS_FALSE;
3658
3659 hdd_deinit_tx_rx(pAdapter);
3660 hdd_wmm_adapter_close(pAdapter);
3661
3662 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3663 pAdapterNode = pNext;
3664 }
3665
3666 EXIT();
3667
3668 return VOS_STATUS_SUCCESS;
3669}
3670
3671VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
3672{
3673 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3674 VOS_STATUS status;
3675 hdd_adapter_t *pAdapter;
3676 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
3677
3678 ENTER();
3679
3680 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3681
3682 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3683 {
3684 pAdapter = pAdapterNode->pAdapter;
3685
3686 switch(pAdapter->device_mode)
3687 {
3688 case WLAN_HDD_INFRA_STATION:
3689 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003690 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003691 hdd_init_station_mode(pAdapter);
3692 /* Open the gates for HDD to receive Wext commands */
3693 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003694 pHddCtx->scan_info.mScanPending = FALSE;
3695 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003696
3697 //Trigger the initial scan
3698 hdd_wlan_initial_scan(pAdapter);
3699
3700 //Indicate disconnect event to supplicant if associated previously
3701 if(pAdapter->sessionCtx.station.bSendDisconnect)
3702 {
3703 union iwreq_data wrqu;
3704 memset(&wrqu, '\0', sizeof(wrqu));
3705 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3706 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3707 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3708 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
3709
Jeff Johnson295189b2012-06-20 16:38:30 -07003710 /* indicate disconnected event to nl80211 */
3711 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
3712 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003713 }
3714 break;
3715
3716 case WLAN_HDD_SOFTAP:
3717 /* softAP can handle SSR */
3718 break;
3719
3720 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003721 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
3722 __func__);
3723 /* event supplicant to restart */
3724 cfg80211_del_sta(pAdapter->dev,
3725 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003726 break;
3727
3728 case WLAN_HDD_MONITOR:
3729 /* monitor interface start */
3730 break;
3731 default:
3732 break;
3733 }
3734
3735 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3736 pAdapterNode = pNext;
3737 }
3738
3739 EXIT();
3740
3741 return VOS_STATUS_SUCCESS;
3742}
3743
3744VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
3745{
3746 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3747 hdd_adapter_t *pAdapter;
3748 VOS_STATUS status;
3749 v_U32_t roamId;
3750
3751 ENTER();
3752
3753 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3754
3755 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3756 {
3757 pAdapter = pAdapterNode->pAdapter;
3758
3759 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3760 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
3761 {
3762 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3763 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3764
3765 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3766 init_completion(&pAdapter->disconnect_comp_var);
3767 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
3768 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3769
3770 wait_for_completion_interruptible_timeout(
3771 &pAdapter->disconnect_comp_var,
3772 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3773
3774 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
3775 pHddCtx->isAmpAllowed = VOS_FALSE;
3776 sme_RoamConnect(pHddCtx->hHal,
3777 pAdapter->sessionId, &(pWextState->roamProfile),
3778 &roamId);
3779 }
3780
3781 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3782 pAdapterNode = pNext;
3783 }
3784
3785 EXIT();
3786
3787 return VOS_STATUS_SUCCESS;
3788}
3789
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07003790void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
3791{
3792 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3793 VOS_STATUS status;
3794 hdd_adapter_t *pAdapter;
3795 hdd_station_ctx_t *pHddStaCtx;
3796 hdd_ap_ctx_t *pHddApCtx;
3797 hdd_hostapd_state_t * pHostapdState;
3798 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
3799 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
3800 const char *p2pMode = "DEV";
3801 const char *ccMode = "Standalone";
3802 int n;
3803
3804 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3805 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3806 {
3807 pAdapter = pAdapterNode->pAdapter;
3808 switch (pAdapter->device_mode) {
3809 case WLAN_HDD_INFRA_STATION:
3810 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3811 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3812 staChannel = pHddStaCtx->conn_info.operationChannel;
3813 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
3814 }
3815 break;
3816 case WLAN_HDD_P2P_CLIENT:
3817 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3818 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3819 p2pChannel = pHddStaCtx->conn_info.operationChannel;
3820 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
3821 p2pMode = "CLI";
3822 }
3823 break;
3824 case WLAN_HDD_P2P_GO:
3825 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3826 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3827 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3828 p2pChannel = pHddApCtx->operatingChannel;
3829 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
3830 }
3831 p2pMode = "GO";
3832 break;
3833 case WLAN_HDD_SOFTAP:
3834 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3835 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3836 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3837 apChannel = pHddApCtx->operatingChannel;
3838 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
3839 }
3840 break;
3841 default:
3842 break;
3843 }
3844 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3845 pAdapterNode = pNext;
3846 }
3847 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
3848 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
3849 }
3850 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
3851 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
3852 if (p2pChannel > 0) {
3853 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
3854 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
3855 }
3856 if (apChannel > 0) {
3857 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
3858 apChannel, MAC_ADDR_ARRAY(apBssid));
3859 }
3860
3861 if (p2pChannel > 0 && apChannel > 0) {
3862 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
3863 }
3864}
3865
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003866bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07003867{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003868 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07003869}
3870
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003871/* Once SSR is disabled then it cannot be set. */
3872void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07003873{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003874 if (HDD_SSR_DISABLED == isSsrRequired)
3875 return;
3876
Jeff Johnson295189b2012-06-20 16:38:30 -07003877 isSsrRequired = value;
3878}
3879
3880VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
3881 hdd_adapter_list_node_t** ppAdapterNode)
3882{
3883 VOS_STATUS status;
3884 spin_lock(&pHddCtx->hddAdapters.lock);
3885 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
3886 (hdd_list_node_t**) ppAdapterNode );
3887 spin_unlock(&pHddCtx->hddAdapters.lock);
3888 return status;
3889}
3890
3891VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
3892 hdd_adapter_list_node_t* pAdapterNode,
3893 hdd_adapter_list_node_t** pNextAdapterNode)
3894{
3895 VOS_STATUS status;
3896 spin_lock(&pHddCtx->hddAdapters.lock);
3897 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
3898 (hdd_list_node_t*) pAdapterNode,
3899 (hdd_list_node_t**)pNextAdapterNode );
3900
3901 spin_unlock(&pHddCtx->hddAdapters.lock);
3902 return status;
3903}
3904
3905VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
3906 hdd_adapter_list_node_t* pAdapterNode)
3907{
3908 VOS_STATUS status;
3909 spin_lock(&pHddCtx->hddAdapters.lock);
3910 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
3911 &pAdapterNode->node );
3912 spin_unlock(&pHddCtx->hddAdapters.lock);
3913 return status;
3914}
3915
3916VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
3917 hdd_adapter_list_node_t** ppAdapterNode)
3918{
3919 VOS_STATUS status;
3920 spin_lock(&pHddCtx->hddAdapters.lock);
3921 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
3922 (hdd_list_node_t**) ppAdapterNode );
3923 spin_unlock(&pHddCtx->hddAdapters.lock);
3924 return status;
3925}
3926
3927VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
3928 hdd_adapter_list_node_t* pAdapterNode)
3929{
3930 VOS_STATUS status;
3931 spin_lock(&pHddCtx->hddAdapters.lock);
3932 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
3933 (hdd_list_node_t*) pAdapterNode );
3934 spin_unlock(&pHddCtx->hddAdapters.lock);
3935 return status;
3936}
3937
3938VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
3939 hdd_adapter_list_node_t* pAdapterNode)
3940{
3941 VOS_STATUS status;
3942 spin_lock(&pHddCtx->hddAdapters.lock);
3943 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
3944 (hdd_list_node_t*) pAdapterNode );
3945 spin_unlock(&pHddCtx->hddAdapters.lock);
3946 return status;
3947}
3948
3949hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
3950 tSirMacAddr macAddr )
3951{
3952 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3953 hdd_adapter_t *pAdapter;
3954 VOS_STATUS status;
3955
3956 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3957
3958 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3959 {
3960 pAdapter = pAdapterNode->pAdapter;
3961
3962 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
3963 macAddr, sizeof(tSirMacAddr) ) )
3964 {
3965 return pAdapter;
3966 }
3967 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3968 pAdapterNode = pNext;
3969 }
3970
3971 return NULL;
3972
3973}
3974
3975hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
3976{
3977 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3978 hdd_adapter_t *pAdapter;
3979 VOS_STATUS status;
3980
3981 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3982
3983 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3984 {
3985 pAdapter = pAdapterNode->pAdapter;
3986
3987 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
3988 IFNAMSIZ ) )
3989 {
3990 return pAdapter;
3991 }
3992 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3993 pAdapterNode = pNext;
3994 }
3995
3996 return NULL;
3997
3998}
3999
4000hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4001{
4002 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4003 hdd_adapter_t *pAdapter;
4004 VOS_STATUS status;
4005
4006 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4007
4008 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4009 {
4010 pAdapter = pAdapterNode->pAdapter;
4011
4012 if( pAdapter && (mode == pAdapter->device_mode) )
4013 {
4014 return pAdapter;
4015 }
4016 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4017 pAdapterNode = pNext;
4018 }
4019
4020 return NULL;
4021
4022}
4023
4024//Remove this function later
4025hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4026{
4027 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4028 hdd_adapter_t *pAdapter;
4029 VOS_STATUS status;
4030
4031 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4032
4033 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4034 {
4035 pAdapter = pAdapterNode->pAdapter;
4036
4037 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4038 {
4039 return pAdapter;
4040 }
4041
4042 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4043 pAdapterNode = pNext;
4044 }
4045
4046 return NULL;
4047
4048}
4049
Jeff Johnson295189b2012-06-20 16:38:30 -07004050/**---------------------------------------------------------------------------
4051
4052 \brief hdd_set_monitor_tx_adapter() -
4053
4054 This API initializes the adapter to be used while transmitting on monitor
4055 adapter.
4056
4057 \param - pHddCtx - Pointer to the HDD context.
4058 pAdapter - Adapter that will used for TX. This can be NULL.
4059 \return - None.
4060 --------------------------------------------------------------------------*/
4061void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4062{
4063 hdd_adapter_t *pMonAdapter;
4064
4065 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4066
4067 if( NULL != pMonAdapter )
4068 {
4069 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4070 }
4071}
Jeff Johnson295189b2012-06-20 16:38:30 -07004072/**---------------------------------------------------------------------------
4073
4074 \brief hdd_select_queue() -
4075
4076 This API returns the operating channel of the requested device mode
4077
4078 \param - pHddCtx - Pointer to the HDD context.
4079 - mode - Device mode for which operating channel is required
4080 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4081 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4082 \return - channel number. "0" id the requested device is not found OR it is not connected.
4083 --------------------------------------------------------------------------*/
4084v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4085{
4086 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4087 VOS_STATUS status;
4088 hdd_adapter_t *pAdapter;
4089 v_U8_t operatingChannel = 0;
4090
4091 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4092
4093 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4094 {
4095 pAdapter = pAdapterNode->pAdapter;
4096
4097 if( mode == pAdapter->device_mode )
4098 {
4099 switch(pAdapter->device_mode)
4100 {
4101 case WLAN_HDD_INFRA_STATION:
4102 case WLAN_HDD_P2P_CLIENT:
4103 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4104 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4105 break;
4106 case WLAN_HDD_SOFTAP:
4107 case WLAN_HDD_P2P_GO:
4108 /*softap connection info */
4109 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4110 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4111 break;
4112 default:
4113 break;
4114 }
4115
4116 break; //Found the device of interest. break the loop
4117 }
4118
4119 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4120 pAdapterNode = pNext;
4121 }
4122 return operatingChannel;
4123}
4124
4125#ifdef WLAN_FEATURE_PACKET_FILTERING
4126/**---------------------------------------------------------------------------
4127
4128 \brief hdd_set_multicast_list() -
4129
4130 This used to set the multicast address list.
4131
4132 \param - dev - Pointer to the WLAN device.
4133 - skb - Pointer to OS packet (sk_buff).
4134 \return - success/fail
4135
4136 --------------------------------------------------------------------------*/
4137static void hdd_set_multicast_list(struct net_device *dev)
4138{
4139 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004140 int mc_count;
4141 int i = 0;
4142 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304143
4144 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004145 {
4146 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304147 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004148 return;
4149 }
4150
4151 if (dev->flags & IFF_ALLMULTI)
4152 {
4153 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004154 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304155 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004156 }
4157 else
4158 {
4159 mc_count = netdev_mc_count(dev);
4160 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004161 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004162 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4163 {
4164 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004165 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304166 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004167 return;
4168 }
4169
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304170 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004171
4172 netdev_for_each_mc_addr(ha, dev) {
4173 if (i == mc_count)
4174 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304175 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4176 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4177 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004178 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304179 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004180 i++;
4181 }
4182 }
4183 return;
4184}
4185#endif
4186
4187/**---------------------------------------------------------------------------
4188
4189 \brief hdd_select_queue() -
4190
4191 This function is registered with the Linux OS for network
4192 core to decide which queue to use first.
4193
4194 \param - dev - Pointer to the WLAN device.
4195 - skb - Pointer to OS packet (sk_buff).
4196 \return - ac, Queue Index/access category corresponding to UP in IP header
4197
4198 --------------------------------------------------------------------------*/
4199v_U16_t hdd_select_queue(struct net_device *dev,
4200 struct sk_buff *skb)
4201{
4202 return hdd_wmm_select_queue(dev, skb);
4203}
4204
4205
4206/**---------------------------------------------------------------------------
4207
4208 \brief hdd_wlan_initial_scan() -
4209
4210 This function triggers the initial scan
4211
4212 \param - pAdapter - Pointer to the HDD adapter.
4213
4214 --------------------------------------------------------------------------*/
4215void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4216{
4217 tCsrScanRequest scanReq;
4218 tCsrChannelInfo channelInfo;
4219 eHalStatus halStatus;
4220 unsigned long scanId;
4221 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4222
4223 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4224 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4225 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4226
4227 if(sme_Is11dSupported(pHddCtx->hHal))
4228 {
4229 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4230 if ( HAL_STATUS_SUCCESS( halStatus ) )
4231 {
4232 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4233 if( !scanReq.ChannelInfo.ChannelList )
4234 {
4235 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4236 vos_mem_free(channelInfo.ChannelList);
4237 return;
4238 }
4239 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4240 channelInfo.numOfChannels);
4241 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4242 vos_mem_free(channelInfo.ChannelList);
4243 }
4244
4245 scanReq.scanType = eSIR_PASSIVE_SCAN;
4246 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4247 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4248 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4249 }
4250 else
4251 {
4252 scanReq.scanType = eSIR_ACTIVE_SCAN;
4253 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4254 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4255 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4256 }
4257
4258 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4259 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4260 {
4261 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4262 __func__, halStatus );
4263 }
4264
4265 if(sme_Is11dSupported(pHddCtx->hHal))
4266 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4267}
4268
4269struct fullPowerContext
4270{
4271 struct completion completion;
4272 unsigned int magic;
4273};
4274#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4275
4276/**---------------------------------------------------------------------------
4277
4278 \brief hdd_full_power_callback() - HDD full power callback function
4279
4280 This is the function invoked by SME to inform the result of a full power
4281 request issued by HDD
4282
4283 \param - callbackcontext - Pointer to cookie
4284 \param - status - result of request
4285
4286 \return - None
4287
4288 --------------------------------------------------------------------------*/
4289static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4290{
4291 struct fullPowerContext *pContext = callbackContext;
4292
4293 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304294 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004295
4296 if (NULL == callbackContext)
4297 {
4298 hddLog(VOS_TRACE_LEVEL_ERROR,
4299 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004300 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004301 return;
4302 }
4303
4304 /* there is a race condition that exists between this callback function
4305 and the caller since the caller could time out either before or
4306 while this code is executing. we'll assume the timeout hasn't
4307 occurred, but we'll verify that right before we save our work */
4308
4309 if (POWER_CONTEXT_MAGIC != pContext->magic)
4310 {
4311 /* the caller presumably timed out so there is nothing we can do */
4312 hddLog(VOS_TRACE_LEVEL_WARN,
4313 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004314 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004315 return;
4316 }
4317
4318 /* the race is on. caller could have timed out immediately after
4319 we verified the magic, but if so, caller will wait a short time
4320 for us to notify the caller, so the context will stay valid */
4321 complete(&pContext->completion);
4322}
4323
4324/**---------------------------------------------------------------------------
4325
4326 \brief hdd_wlan_exit() - HDD WLAN exit function
4327
4328 This is the driver exit point (invoked during rmmod)
4329
4330 \param - pHddCtx - Pointer to the HDD Context
4331
4332 \return - None
4333
4334 --------------------------------------------------------------------------*/
4335void hdd_wlan_exit(hdd_context_t *pHddCtx)
4336{
4337 eHalStatus halStatus;
4338 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4339 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304340 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004341 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004342 struct fullPowerContext powerContext;
4343 long lrc;
4344
4345 ENTER();
4346
Jeff Johnson88ba7742013-02-27 14:36:02 -08004347 if (VOS_FTM_MODE != hdd_get_conparam())
4348 {
4349 // Unloading, restart logic is no more required.
4350 wlan_hdd_restart_deinit(pHddCtx);
4351 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004352
Jeff Johnson295189b2012-06-20 16:38:30 -07004353 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004354 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004355 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004356 {
4357 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4358 WLAN_HDD_INFRA_STATION);
4359 if (pAdapter == NULL)
4360 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4361
4362 if (pAdapter != NULL)
4363 {
4364 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4365 hdd_UnregisterWext(pAdapter->dev);
4366 }
4367 }
4368 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004369
Jeff Johnson295189b2012-06-20 16:38:30 -07004370 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004371 {
4372 wlan_hdd_ftm_close(pHddCtx);
4373 goto free_hdd_ctx;
4374 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004375 //Stop the Interface TX queue.
4376 //netif_tx_disable(pWlanDev);
4377 //netif_carrier_off(pWlanDev);
4378
Jeff Johnson295189b2012-06-20 16:38:30 -07004379 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4380 {
4381 pAdapter = hdd_get_adapter(pHddCtx,
4382 WLAN_HDD_SOFTAP);
4383 }
4384 else
4385 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004386 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004387 {
4388 pAdapter = hdd_get_adapter(pHddCtx,
4389 WLAN_HDD_INFRA_STATION);
4390 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004391 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004392 /* DeRegister with platform driver as client for Suspend/Resume */
4393 vosStatus = hddDeregisterPmOps(pHddCtx);
4394 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4395 {
4396 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4397 VOS_ASSERT(0);
4398 }
4399
4400 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4401 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4402 {
4403 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4404 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004405
4406 // Cancel any outstanding scan requests. We are about to close all
4407 // of our adapters, but an adapter structure is what SME passes back
4408 // to our callback function. Hence if there are any outstanding scan
4409 // requests then there is a race condition between when the adapter
4410 // is closed and when the callback is invoked. We try to resolve that
4411 // race condition here by canceling any outstanding scans before we
4412 // close the adapters.
4413 // Note that the scans may be cancelled in an asynchronous manner, so
4414 // ideally there needs to be some kind of synchronization. Rather than
4415 // introduce a new synchronization here, we will utilize the fact that
4416 // we are about to Request Full Power, and since that is synchronized,
4417 // the expectation is that by the time Request Full Power has completed,
4418 // all scans will be cancelled.
4419 hdd_abort_mac_scan( pHddCtx );
4420
4421 //Disable IMPS/BMPS as we do not want the device to enter any power
4422 //save mode during shutdown
4423 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4424 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4425 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4426
4427 //Ensure that device is in full power as we will touch H/W during vos_Stop
4428 init_completion(&powerContext.completion);
4429 powerContext.magic = POWER_CONTEXT_MAGIC;
4430
4431 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4432 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4433
4434 if (eHAL_STATUS_SUCCESS != halStatus)
4435 {
4436 if (eHAL_STATUS_PMC_PENDING == halStatus)
4437 {
4438 /* request was sent -- wait for the response */
4439 lrc = wait_for_completion_interruptible_timeout(
4440 &powerContext.completion,
4441 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4442 /* either we have a response or we timed out
4443 either way, first invalidate our magic */
4444 powerContext.magic = 0;
4445 if (lrc <= 0)
4446 {
4447 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004448 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004449 /* there is a race condition such that the callback
4450 function could be executing at the same time we are. of
4451 primary concern is if the callback function had already
4452 verified the "magic" but hasn't yet set the completion
4453 variable. Since the completion variable is on our
4454 stack, we'll delay just a bit to make sure the data is
4455 still valid if that is the case */
4456 msleep(50);
4457 }
4458 }
4459 else
4460 {
4461 hddLog(VOS_TRACE_LEVEL_ERROR,
4462 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004463 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004464 VOS_ASSERT(0);
4465 /* continue -- need to clean up as much as possible */
4466 }
4467 }
4468
4469 // Unregister the Net Device Notifier
4470 unregister_netdevice_notifier(&hdd_netdev_notifier);
4471
Jeff Johnson295189b2012-06-20 16:38:30 -07004472 hdd_stop_all_adapters( pHddCtx );
4473
Jeff Johnson295189b2012-06-20 16:38:30 -07004474#ifdef WLAN_BTAMP_FEATURE
4475 vosStatus = WLANBAP_Stop(pVosContext);
4476 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4477 {
4478 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4479 "%s: Failed to stop BAP",__func__);
4480 }
4481#endif //WLAN_BTAMP_FEATURE
4482
4483 //Stop all the modules
4484 vosStatus = vos_stop( pVosContext );
4485 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4486 {
4487 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4488 "%s: Failed to stop VOSS",__func__);
4489 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4490 }
4491
Jeff Johnson295189b2012-06-20 16:38:30 -07004492 //Assert Deep sleep signal now to put Libra HW in lowest power state
4493 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4494 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4495
4496 //Vote off any PMIC voltage supplies
4497 vos_chipPowerDown(NULL, NULL, NULL);
4498
4499 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4500
4501 //Clean up HDD Nlink Service
4502 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
4503 nl_srv_exit();
4504
4505 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004506 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004507
4508 //Close the scheduler before calling vos_close to make sure no thread is
4509 // scheduled after the each module close is called i.e after all the data
4510 // structures are freed.
4511 vosStatus = vos_sched_close( pVosContext );
4512 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4513 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4514 "%s: Failed to close VOSS Scheduler",__func__);
4515 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4516 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004517#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004518#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4519 /* Destroy the wake lock */
4520 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4521#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004522 /* Destroy the wake lock */
4523 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004524#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004525
4526 //Close VOSS
4527 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4528 vos_close(pVosContext);
4529
Jeff Johnson295189b2012-06-20 16:38:30 -07004530 //Close Watchdog
4531 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4532 vos_watchdog_close(pVosContext);
4533
4534 /* Cancel the vote for XO Core ON.
4535 * This is done here to ensure there is no race condition since MC, TX and WD threads have
4536 * exited at this point
4537 */
4538 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
4539 " when WLAN is turned OFF\n");
4540 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4541 {
4542 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
4543 " Not returning failure."
4544 " Power consumed will be high\n");
4545 }
4546
4547 hdd_close_all_adapters( pHddCtx );
4548
4549
4550 //Free up dynamically allocated members inside HDD Adapter
4551 kfree(pHddCtx->cfg_ini);
4552 pHddCtx->cfg_ini= NULL;
4553
4554 /* free the power on lock from platform driver */
4555 if (free_riva_power_on_lock("wlan"))
4556 {
4557 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
4558 __func__);
4559 }
4560
Jeff Johnson88ba7742013-02-27 14:36:02 -08004561free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08004562 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004563 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004564 if (hdd_is_ssr_required())
4565 {
4566 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07004567 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07004568 msleep(5000);
4569 }
4570 hdd_set_ssr_required (VOS_FALSE);
4571}
4572
4573
4574/**---------------------------------------------------------------------------
4575
4576 \brief hdd_update_config_from_nv() - Function to update the contents of
4577 the running configuration with parameters taken from NV storage
4578
4579 \param - pHddCtx - Pointer to the HDD global context
4580
4581 \return - VOS_STATUS_SUCCESS if successful
4582
4583 --------------------------------------------------------------------------*/
4584static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
4585{
Jeff Johnson295189b2012-06-20 16:38:30 -07004586 v_BOOL_t itemIsValid = VOS_FALSE;
4587 VOS_STATUS status;
4588 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
4589 v_U8_t macLoop;
4590
4591 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
4592 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
4593 if(status != VOS_STATUS_SUCCESS)
4594 {
4595 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
4596 return VOS_STATUS_E_FAILURE;
4597 }
4598
4599 if (itemIsValid == VOS_TRUE)
4600 {
4601 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
4602 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
4603 VOS_MAX_CONCURRENCY_PERSONA);
4604 if(status != VOS_STATUS_SUCCESS)
4605 {
4606 /* Get MAC from NV fail, not update CFG info
4607 * INI MAC value will be used for MAC setting */
4608 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
4609 return VOS_STATUS_E_FAILURE;
4610 }
4611
4612 /* If first MAC is not valid, treat all others are not valid
4613 * Then all MACs will be got from ini file */
4614 if(vos_is_macaddr_zero(&macFromNV[0]))
4615 {
4616 /* MAC address in NV file is not configured yet */
4617 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
4618 return VOS_STATUS_E_INVAL;
4619 }
4620
4621 /* Get MAC address from NV, update CFG info */
4622 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
4623 {
4624 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
4625 {
4626 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
4627 /* This MAC is not valid, skip it
4628 * This MAC will be got from ini file */
4629 }
4630 else
4631 {
4632 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
4633 (v_U8_t *)&macFromNV[macLoop].bytes[0],
4634 VOS_MAC_ADDR_SIZE);
4635 }
4636 }
4637 }
4638 else
4639 {
4640 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
4641 return VOS_STATUS_E_FAILURE;
4642 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004643
Jeff Johnson295189b2012-06-20 16:38:30 -07004644
4645 return VOS_STATUS_SUCCESS;
4646}
4647
4648/**---------------------------------------------------------------------------
4649
4650 \brief hdd_post_voss_start_config() - HDD post voss start config helper
4651
4652 \param - pAdapter - Pointer to the HDD
4653
4654 \return - None
4655
4656 --------------------------------------------------------------------------*/
4657VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
4658{
4659 eHalStatus halStatus;
4660 v_U32_t listenInterval;
4661
Jeff Johnson295189b2012-06-20 16:38:30 -07004662
4663 // Send ready indication to the HDD. This will kick off the MAC
4664 // into a 'running' state and should kick off an initial scan.
4665 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
4666 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4667 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304668 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07004669 "code %08d [x%08x]",__func__, halStatus, halStatus );
4670 return VOS_STATUS_E_FAILURE;
4671 }
4672
4673 // Set default LI into HDD context,
4674 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
4675 // And RIVA will crash
4676 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
4677 pHddCtx->hdd_actual_LI_value = listenInterval;
4678
4679 return VOS_STATUS_SUCCESS;
4680}
4681
Jeff Johnson295189b2012-06-20 16:38:30 -07004682/* wake lock APIs for HDD */
4683void hdd_prevent_suspend(void)
4684{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004685#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004686 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004687#else
4688 wcnss_prevent_suspend();
4689#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004690}
4691
4692void hdd_allow_suspend(void)
4693{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004694#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004695 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004696#else
4697 wcnss_allow_suspend();
4698#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004699}
4700
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004701void hdd_allow_suspend_timeout(v_U32_t timeout)
4702{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004703#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07004704 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004705#else
4706 /* Do nothing as there is no API in wcnss for timeout*/
4707#endif
4708}
4709
Jeff Johnson295189b2012-06-20 16:38:30 -07004710/**---------------------------------------------------------------------------
4711
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004712 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
4713 information between Host and Riva
4714
4715 This function gets reported version of FW
4716 It also finds the version of Riva headers used to compile the host
4717 It compares the above two and prints a warning if they are different
4718 It gets the SW and HW version string
4719 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
4720 indicating the features they support through a bitmap
4721
4722 \param - pHddCtx - Pointer to HDD context
4723
4724 \return - void
4725
4726 --------------------------------------------------------------------------*/
4727
4728void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
4729{
4730
4731 tSirVersionType versionCompiled;
4732 tSirVersionType versionReported;
4733 tSirVersionString versionString;
4734 tANI_U8 fwFeatCapsMsgSupported = 0;
4735 VOS_STATUS vstatus;
4736
4737 /* retrieve and display WCNSS version information */
4738 do {
4739
4740 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
4741 &versionCompiled);
4742 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4743 {
4744 hddLog(VOS_TRACE_LEVEL_FATAL,
4745 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004746 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004747 break;
4748 }
4749
4750 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
4751 &versionReported);
4752 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4753 {
4754 hddLog(VOS_TRACE_LEVEL_FATAL,
4755 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004756 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004757 break;
4758 }
4759
4760 if ((versionCompiled.major != versionReported.major) ||
4761 (versionCompiled.minor != versionReported.minor) ||
4762 (versionCompiled.version != versionReported.version) ||
4763 (versionCompiled.revision != versionReported.revision))
4764 {
4765 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4766 "Host expected %u.%u.%u.%u\n",
4767 WLAN_MODULE_NAME,
4768 (int)versionReported.major,
4769 (int)versionReported.minor,
4770 (int)versionReported.version,
4771 (int)versionReported.revision,
4772 (int)versionCompiled.major,
4773 (int)versionCompiled.minor,
4774 (int)versionCompiled.version,
4775 (int)versionCompiled.revision);
4776 }
4777 else
4778 {
4779 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4780 WLAN_MODULE_NAME,
4781 (int)versionReported.major,
4782 (int)versionReported.minor,
4783 (int)versionReported.version,
4784 (int)versionReported.revision);
4785 }
4786
4787 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
4788 versionString,
4789 sizeof(versionString));
4790 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4791 {
4792 hddLog(VOS_TRACE_LEVEL_FATAL,
4793 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004794 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004795 break;
4796 }
4797
4798 pr_info("%s: WCNSS software version %s\n",
4799 WLAN_MODULE_NAME, versionString);
4800
4801 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
4802 versionString,
4803 sizeof(versionString));
4804 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4805 {
4806 hddLog(VOS_TRACE_LEVEL_FATAL,
4807 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004808 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004809 break;
4810 }
4811
4812 pr_info("%s: WCNSS hardware version %s\n",
4813 WLAN_MODULE_NAME, versionString);
4814
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004815 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
4816 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004817 send the message only if it the riva is 1.1
4818 minor numbers for different riva branches:
4819 0 -> (1.0)Mainline Build
4820 1 -> (1.1)Mainline Build
4821 2->(1.04) Stability Build
4822 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004823 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004824 ((versionReported.minor>=1) && (versionReported.version>=1)))
4825 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
4826 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004827
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004828 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08004829 {
4830#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4831 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
4832 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
4833#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004834 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08004835 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004836
4837 } while (0);
4838
4839}
4840
4841/**---------------------------------------------------------------------------
4842
Jeff Johnson295189b2012-06-20 16:38:30 -07004843 \brief hdd_wlan_startup() - HDD init function
4844
4845 This is the driver startup code executed once a WLAN device has been detected
4846
4847 \param - dev - Pointer to the underlying device
4848
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004849 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07004850
4851 --------------------------------------------------------------------------*/
4852
4853int hdd_wlan_startup(struct device *dev )
4854{
4855 VOS_STATUS status;
4856 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004857 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004858 hdd_context_t *pHddCtx = NULL;
4859 v_CONTEXT_t pVosContext= NULL;
4860#ifdef WLAN_BTAMP_FEATURE
4861 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
4862 WLANBAP_ConfigType btAmpConfig;
4863 hdd_config_t *pConfig;
4864#endif
4865 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07004866 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004867
4868 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07004869 /*
4870 * cfg80211: wiphy allocation
4871 */
4872 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
4873
4874 if(wiphy == NULL)
4875 {
4876 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004877 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004878 }
4879
4880 pHddCtx = wiphy_priv(wiphy);
4881
Jeff Johnson295189b2012-06-20 16:38:30 -07004882 //Initialize the adapter context to zeros.
4883 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
4884
Jeff Johnson295189b2012-06-20 16:38:30 -07004885 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004886 hdd_prevent_suspend();
4887 pHddCtx->isLoadUnloadInProgress = TRUE;
4888
4889 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4890
4891 /*Get vos context here bcoz vos_open requires it*/
4892 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4893
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08004894 if(pVosContext == NULL)
4895 {
4896 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
4897 goto err_free_hdd_context;
4898 }
4899
Jeff Johnson295189b2012-06-20 16:38:30 -07004900 //Save the Global VOSS context in adapter context for future.
4901 pHddCtx->pvosContext = pVosContext;
4902
4903 //Save the adapter context in global context for future.
4904 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
4905
Jeff Johnson295189b2012-06-20 16:38:30 -07004906 pHddCtx->parent_dev = dev;
4907
4908 init_completion(&pHddCtx->full_pwr_comp_var);
4909 init_completion(&pHddCtx->standby_comp_var);
4910 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004911 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004912 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004913
4914 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
4915
4916 // Load all config first as TL config is needed during vos_open
4917 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
4918 if(pHddCtx->cfg_ini == NULL)
4919 {
4920 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
4921 goto err_free_hdd_context;
4922 }
4923
4924 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
4925
4926 // Read and parse the qcom_cfg.ini file
4927 status = hdd_parse_config_ini( pHddCtx );
4928 if ( VOS_STATUS_SUCCESS != status )
4929 {
4930 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
4931 __func__, WLAN_INI_FILE);
4932 goto err_config;
4933 }
4934
Jeff Johnson295189b2012-06-20 16:38:30 -07004935 /*
4936 * cfg80211: Initialization and registration ...
4937 */
4938 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
4939 {
4940 hddLog(VOS_TRACE_LEVEL_FATAL,
4941 "%s: wlan_hdd_cfg80211_register return failure", __func__);
4942 goto err_wiphy_reg;
4943 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004944
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004945 // Update VOS trace levels based upon the cfg.ini
4946 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
4947 pHddCtx->cfg_ini->vosTraceEnableBAP);
4948 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
4949 pHddCtx->cfg_ini->vosTraceEnableTL);
4950 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
4951 pHddCtx->cfg_ini->vosTraceEnableWDI);
4952 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
4953 pHddCtx->cfg_ini->vosTraceEnableHDD);
4954 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
4955 pHddCtx->cfg_ini->vosTraceEnableSME);
4956 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
4957 pHddCtx->cfg_ini->vosTraceEnablePE);
4958 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
4959 pHddCtx->cfg_ini->vosTraceEnableWDA);
4960 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
4961 pHddCtx->cfg_ini->vosTraceEnableSYS);
4962 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
4963 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004964 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
4965 pHddCtx->cfg_ini->vosTraceEnableSAP);
4966 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
4967 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004968
Jeff Johnson295189b2012-06-20 16:38:30 -07004969 // Update WDI trace levels based upon the cfg.ini
4970 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
4971 pHddCtx->cfg_ini->wdiTraceEnableDAL);
4972 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
4973 pHddCtx->cfg_ini->wdiTraceEnableCTL);
4974 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
4975 pHddCtx->cfg_ini->wdiTraceEnableDAT);
4976 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
4977 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004978
Jeff Johnson88ba7742013-02-27 14:36:02 -08004979 if (VOS_FTM_MODE == hdd_get_conparam())
4980 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004981 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
4982 {
4983 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
4984 goto err_free_hdd_context;
4985 }
4986 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
4987 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08004988 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004989
Jeff Johnson88ba7742013-02-27 14:36:02 -08004990 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07004991 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4992 {
4993 status = vos_watchdog_open(pVosContext,
4994 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
4995
4996 if(!VOS_IS_STATUS_SUCCESS( status ))
4997 {
4998 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004999 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005000 }
5001 }
5002
5003 pHddCtx->isLogpInProgress = FALSE;
5004 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5005
Jeff Johnson295189b2012-06-20 16:38:30 -07005006 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5007 if(!VOS_IS_STATUS_SUCCESS(status))
5008 {
5009 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005010 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005011 }
5012
Jeff Johnson295189b2012-06-20 16:38:30 -07005013 status = vos_open( &pVosContext, 0);
5014 if ( !VOS_IS_STATUS_SUCCESS( status ))
5015 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005016 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5017 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005018 }
5019
Jeff Johnson295189b2012-06-20 16:38:30 -07005020 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5021
5022 if ( NULL == pHddCtx->hHal )
5023 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005024 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005025 goto err_vosclose;
5026 }
5027
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005028 status = vos_preStart( pHddCtx->pvosContext );
5029 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5030 {
5031 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5032 goto err_vosclose;
5033 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005034
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005035 /* Note that the vos_preStart() sequence triggers the cfg download.
5036 The cfg download must occur before we update the SME config
5037 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005038 status = hdd_set_sme_config( pHddCtx );
5039
5040 if ( VOS_STATUS_SUCCESS != status )
5041 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005042 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5043 goto err_vosclose;
5044 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005045
5046 //Initialize the WMM module
5047 status = hdd_wmm_init(pHddCtx);
5048 if (!VOS_IS_STATUS_SUCCESS(status))
5049 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005050 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005051 goto err_vosclose;
5052 }
5053
Jeff Johnson295189b2012-06-20 16:38:30 -07005054 /* In the integrated architecture we update the configuration from
5055 the INI file and from NV before vOSS has been started so that
5056 the final contents are available to send down to the cCPU */
5057
5058 // Apply the cfg.ini to cfg.dat
5059 if (FALSE == hdd_update_config_dat(pHddCtx))
5060 {
5061 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5062 goto err_vosclose;
5063 }
5064
5065 // Apply the NV to cfg.dat
5066 /* Prima Update MAC address only at here */
5067 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5068 {
5069#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5070 /* There was not a valid set of MAC Addresses in NV. See if the
5071 default addresses were modified by the cfg.ini settings. If so,
5072 we'll use them, but if not, we'll autogenerate a set of MAC
5073 addresses based upon the device serial number */
5074
5075 static const v_MACADDR_t default_address =
5076 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5077 unsigned int serialno;
5078 int i;
5079
5080 serialno = wcnss_get_serial_number();
5081 if ((0 != serialno) &&
5082 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5083 sizeof(default_address))))
5084 {
5085 /* cfg.ini has the default address, invoke autogen logic */
5086
5087 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5088 bytes of the serial number that can be used to generate
5089 the other 3 bytes of the MAC address. Mask off all but
5090 the lower 3 bytes (this will also make sure we don't
5091 overflow in the next step) */
5092 serialno &= 0x00FFFFFF;
5093
5094 /* we need a unique address for each session */
5095 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5096
5097 /* autogen all addresses */
5098 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5099 {
5100 /* start with the entire default address */
5101 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5102 /* then replace the lower 3 bytes */
5103 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5104 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5105 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5106
5107 serialno++;
5108 }
5109
5110 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5111 MAC_ADDRESS_STR,
5112 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5113 }
5114 else
5115#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5116 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005117 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005118 "%s: Invalid MAC address in NV, using MAC from ini file "
5119 MAC_ADDRESS_STR, __func__,
5120 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5121 }
5122 }
5123 {
5124 eHalStatus halStatus;
5125 // Set the MAC Address
5126 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5127 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5128 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5129 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5130
5131 if (!HAL_STATUS_SUCCESS( halStatus ))
5132 {
5133 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5134 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005135 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005136 }
5137 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005138
5139 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5140 Note: Firmware image will be read and downloaded inside vos_start API */
5141 status = vos_start( pHddCtx->pvosContext );
5142 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5143 {
5144 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5145 goto err_vosclose;
5146 }
5147
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005148 /* Exchange capability info between Host and FW and also get versioning info from FW */
5149 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005150
5151 status = hdd_post_voss_start_config( pHddCtx );
5152 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5153 {
5154 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5155 __func__);
5156 goto err_vosstop;
5157 }
5158
Jeff Johnson295189b2012-06-20 16:38:30 -07005159 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5160 {
5161 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5162 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5163 }
5164 else
5165 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005166 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5167 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5168 if (pAdapter != NULL)
5169 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305170 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005171 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305172 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5173 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5174 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005175
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305176 /* Generate the P2P Device Address. This consists of the device's
5177 * primary MAC address with the locally administered bit set.
5178 */
5179 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005180 }
5181 else
5182 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305183 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5184 if (p2p_dev_addr != NULL)
5185 {
5186 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5187 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5188 }
5189 else
5190 {
5191 hddLog(VOS_TRACE_LEVEL_FATAL,
5192 "%s: Failed to allocate mac_address for p2p_device",
5193 __func__);
5194 goto err_close_adapter;
5195 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005196 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005197
5198 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5199 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5200 if ( NULL == pP2pAdapter )
5201 {
5202 hddLog(VOS_TRACE_LEVEL_FATAL,
5203 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005204 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005205 goto err_close_adapter;
5206 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005207 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005208 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005209
5210 if( pAdapter == NULL )
5211 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005212 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5213 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005214 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005215
Jeff Johnson295189b2012-06-20 16:38:30 -07005216#ifdef WLAN_BTAMP_FEATURE
5217 vStatus = WLANBAP_Open(pVosContext);
5218 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5219 {
5220 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5221 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005222 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005223 }
5224
5225 vStatus = BSL_Init(pVosContext);
5226 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5227 {
5228 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5229 "%s: Failed to Init BSL",__func__);
5230 goto err_bap_close;
5231 }
5232 vStatus = WLANBAP_Start(pVosContext);
5233 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5234 {
5235 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5236 "%s: Failed to start TL",__func__);
5237 goto err_bap_close;
5238 }
5239
5240 pConfig = pHddCtx->cfg_ini;
5241 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5242 status = WLANBAP_SetConfig(&btAmpConfig);
5243
5244#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005245
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005246#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5247 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5248 {
5249 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5250 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5251 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5252 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5253 }
5254#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005255#ifdef FEATURE_WLAN_SCAN_PNO
5256 /*SME must send channel update configuration to RIVA*/
5257 sme_UpdateChannelConfig(pHddCtx->hHal);
5258#endif
5259
Jeff Johnson295189b2012-06-20 16:38:30 -07005260 /* Register with platform driver as client for Suspend/Resume */
5261 status = hddRegisterPmOps(pHddCtx);
5262 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5263 {
5264 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5265#ifdef WLAN_BTAMP_FEATURE
5266 goto err_bap_stop;
5267#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005268 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005269#endif //WLAN_BTAMP_FEATURE
5270 }
5271
5272 /* Register TM level change handler function to the platform */
5273 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5274 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5275 {
5276 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5277 goto err_unregister_pmops;
5278 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005279
5280 /* register for riva power on lock to platform driver */
5281 if (req_riva_power_on_lock("wlan"))
5282 {
5283 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5284 __func__);
5285 goto err_unregister_pmops;
5286 }
5287
Jeff Johnson295189b2012-06-20 16:38:30 -07005288 // register net device notifier for device change notification
5289 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5290
5291 if(ret < 0)
5292 {
5293 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5294 goto err_free_power_on_lock;
5295 }
5296
5297 //Initialize the nlink service
5298 if(nl_srv_init() != 0)
5299 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305300 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005301 goto err_reg_netdev;
5302 }
5303
5304 //Initialize the BTC service
5305 if(btc_activate_service(pHddCtx) != 0)
5306 {
5307 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5308 goto err_nl_srv;
5309 }
5310
5311#ifdef PTT_SOCK_SVC_ENABLE
5312 //Initialize the PTT service
5313 if(ptt_sock_activate_svc(pHddCtx) != 0)
5314 {
5315 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5316 goto err_nl_srv;
5317 }
5318#endif
5319
Jeff Johnson295189b2012-06-20 16:38:30 -07005320 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005321 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005322 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005323 /* Action frame registered in one adapter which will
5324 * applicable to all interfaces
5325 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005326 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005327 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005328
5329 mutex_init(&pHddCtx->sap_lock);
5330
5331 pHddCtx->isLoadUnloadInProgress = FALSE;
5332
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005333#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005334#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5335 /* Initialize the wake lcok */
5336 wake_lock_init(&pHddCtx->rx_wake_lock,
5337 WAKE_LOCK_SUSPEND,
5338 "qcom_rx_wakelock");
5339#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005340 /* Initialize the wake lcok */
5341 wake_lock_init(&pHddCtx->sap_wake_lock,
5342 WAKE_LOCK_SUSPEND,
5343 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005344#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005345
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005346 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5347 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005348
5349 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5350 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005351
5352 // Initialize the restart logic
5353 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305354
Jeff Johnson295189b2012-06-20 16:38:30 -07005355 goto success;
5356
5357err_nl_srv:
5358 nl_srv_exit();
5359
5360err_reg_netdev:
5361 unregister_netdevice_notifier(&hdd_netdev_notifier);
5362
5363err_free_power_on_lock:
5364 free_riva_power_on_lock("wlan");
5365
5366err_unregister_pmops:
5367 hddDevTmUnregisterNotifyCallback(pHddCtx);
5368 hddDeregisterPmOps(pHddCtx);
5369
5370#ifdef WLAN_BTAMP_FEATURE
5371err_bap_stop:
5372 WLANBAP_Stop(pVosContext);
5373#endif
5374
5375#ifdef WLAN_BTAMP_FEATURE
5376err_bap_close:
5377 WLANBAP_Close(pVosContext);
5378#endif
5379
Jeff Johnson295189b2012-06-20 16:38:30 -07005380err_close_adapter:
5381 hdd_close_all_adapters( pHddCtx );
5382
5383err_vosstop:
5384 vos_stop(pVosContext);
5385
5386err_vosclose:
5387 status = vos_sched_close( pVosContext );
5388 if (!VOS_IS_STATUS_SUCCESS(status)) {
5389 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5390 "%s: Failed to close VOSS Scheduler", __func__);
5391 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5392 }
5393 vos_close(pVosContext );
5394
Jeff Johnson295189b2012-06-20 16:38:30 -07005395err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005396 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005397
5398err_wdclose:
5399 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5400 vos_watchdog_close(pVosContext);
5401
Jeff Johnson295189b2012-06-20 16:38:30 -07005402err_wiphy_reg:
5403 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005404
5405err_config:
5406 kfree(pHddCtx->cfg_ini);
5407 pHddCtx->cfg_ini= NULL;
5408
5409err_free_hdd_context:
5410 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005411 wiphy_free(wiphy) ;
5412 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005413 VOS_BUG(1);
5414
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005415 if (hdd_is_ssr_required())
5416 {
5417 /* WDI timeout had happened during load, so SSR is needed here */
5418 subsystem_restart("wcnss");
5419 msleep(5000);
5420 }
5421 hdd_set_ssr_required (VOS_FALSE);
5422
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005423 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005424
5425success:
5426 EXIT();
5427 return 0;
5428}
5429
5430/**---------------------------------------------------------------------------
5431
Jeff Johnson32d95a32012-09-10 13:15:23 -07005432 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07005433
Jeff Johnson32d95a32012-09-10 13:15:23 -07005434 This is the driver entry point - called in different timeline depending
5435 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07005436
5437 \param - None
5438
5439 \return - 0 for success, non zero for failure
5440
5441 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07005442static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005443{
5444 VOS_STATUS status;
5445 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005446 struct device *dev = NULL;
5447 int ret_status = 0;
5448
5449 ENTER();
5450
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005451#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005452 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07005453#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005454
5455 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
5456 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
5457
5458 //Power Up Libra WLAN card first if not already powered up
5459 status = vos_chipPowerUp(NULL,NULL,NULL);
5460 if (!VOS_IS_STATUS_SUCCESS(status))
5461 {
5462 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
5463 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005464 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005465 }
5466
Jeff Johnson295189b2012-06-20 16:38:30 -07005467#ifdef ANI_BUS_TYPE_PCI
5468
5469 dev = wcnss_wlan_get_device();
5470
5471#endif // ANI_BUS_TYPE_PCI
5472
5473#ifdef ANI_BUS_TYPE_PLATFORM
5474 dev = wcnss_wlan_get_device();
5475#endif // ANI_BUS_TYPE_PLATFORM
5476
5477
5478 do {
5479 if (NULL == dev) {
5480 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
5481 ret_status = -1;
5482 break;
5483 }
5484
5485#ifdef MEMORY_DEBUG
5486 vos_mem_init();
5487#endif
5488
5489#ifdef TIMER_MANAGER
5490 vos_timer_manager_init();
5491#endif
5492
5493 /* Preopen VOSS so that it is ready to start at least SAL */
5494 status = vos_preOpen(&pVosContext);
5495
5496 if (!VOS_IS_STATUS_SUCCESS(status))
5497 {
5498 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
5499 ret_status = -1;
5500 break;
5501 }
5502
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005503#ifndef MODULE
5504 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
5505 */
5506 hdd_set_conparam((v_UINT_t)con_mode);
5507#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005508
5509 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005510 if (hdd_wlan_startup(dev))
5511 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005512 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005513 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005514 vos_preClose( &pVosContext );
5515 ret_status = -1;
5516 break;
5517 }
5518
5519 /* Cancel the vote for XO Core ON
5520 * This is done here for safety purposes in case we re-initialize without turning
5521 * it OFF in any error scenario.
5522 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005523 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07005524 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005525 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07005526 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5527 {
5528 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
5529 " Power consumed will be high\n");
5530 }
5531 } while (0);
5532
5533 if (0 != ret_status)
5534 {
5535 //Assert Deep sleep signal now to put Libra HW in lowest power state
5536 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5537 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
5538
5539 //Vote off any PMIC voltage supplies
5540 vos_chipPowerDown(NULL, NULL, NULL);
5541#ifdef TIMER_MANAGER
5542 vos_timer_exit();
5543#endif
5544#ifdef MEMORY_DEBUG
5545 vos_mem_exit();
5546#endif
5547
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005548#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005549 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005550#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005551 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
5552 }
5553 else
5554 {
5555 //Send WLAN UP indication to Nlink Service
5556 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
5557
5558 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
5559
5560 }
5561
5562 EXIT();
5563
5564 return ret_status;
5565}
5566
Jeff Johnson32d95a32012-09-10 13:15:23 -07005567/**---------------------------------------------------------------------------
5568
5569 \brief hdd_module_init() - Init Function
5570
5571 This is the driver entry point (invoked when module is loaded using insmod)
5572
5573 \param - None
5574
5575 \return - 0 for success, non zero for failure
5576
5577 --------------------------------------------------------------------------*/
5578#ifdef MODULE
5579static int __init hdd_module_init ( void)
5580{
5581 return hdd_driver_init();
5582}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005583#else /* #ifdef MODULE */
5584static int __init hdd_module_init ( void)
5585{
5586 /* Driver initialization is delayed to fwpath_changed_handler */
5587 return 0;
5588}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005589#endif /* #ifdef MODULE */
5590
Jeff Johnson295189b2012-06-20 16:38:30 -07005591
5592/**---------------------------------------------------------------------------
5593
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005594 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005595
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005596 This is the driver exit point (invoked when module is unloaded using rmmod
5597 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07005598
5599 \param - None
5600
5601 \return - None
5602
5603 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005604static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005605{
5606 hdd_context_t *pHddCtx = NULL;
5607 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005608
5609 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
5610
5611 //Get the global vos context
5612 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5613
5614 if(!pVosContext)
5615 {
5616 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
5617 goto done;
5618 }
5619
5620 //Get the HDD context.
5621 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
5622
5623 if(!pHddCtx)
5624 {
5625 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
5626 }
5627 else
5628 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005629 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07005630 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07005631 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
5632 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07005633 }
5634
5635 pHddCtx->isLoadUnloadInProgress = TRUE;
5636 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5637
5638 //Do all the cleanup before deregistering the driver
5639 hdd_wlan_exit(pHddCtx);
5640 }
5641
Jeff Johnson295189b2012-06-20 16:38:30 -07005642 vos_preClose( &pVosContext );
5643
5644#ifdef TIMER_MANAGER
5645 vos_timer_exit();
5646#endif
5647#ifdef MEMORY_DEBUG
5648 vos_mem_exit();
5649#endif
5650
5651done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005652#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005653 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005654#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005655 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
5656}
5657
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005658/**---------------------------------------------------------------------------
5659
5660 \brief hdd_module_exit() - Exit function
5661
5662 This is the driver exit point (invoked when module is unloaded using rmmod)
5663
5664 \param - None
5665
5666 \return - None
5667
5668 --------------------------------------------------------------------------*/
5669static void __exit hdd_module_exit(void)
5670{
5671 hdd_driver_exit();
5672}
5673
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005674#ifdef MODULE
5675static int fwpath_changed_handler(const char *kmessage,
5676 struct kernel_param *kp)
5677{
Jeff Johnson76052702013-04-16 13:55:05 -07005678 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005679}
5680
5681static int con_mode_handler(const char *kmessage,
5682 struct kernel_param *kp)
5683{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07005684 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005685}
5686#else /* #ifdef MODULE */
5687/**---------------------------------------------------------------------------
5688
Jeff Johnson76052702013-04-16 13:55:05 -07005689 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005690
Jeff Johnson76052702013-04-16 13:55:05 -07005691 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005692 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07005693 - invoked when module parameter fwpath is modified from userspace to signal
5694 initializing the WLAN driver or when con_mode is modified from userspace
5695 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005696
5697 \return - 0 for success, non zero for failure
5698
5699 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07005700static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005701{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005702 int ret_status;
5703
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005704 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005705 ret_status = hdd_driver_init();
5706 wlan_hdd_inited = ret_status ? 0 : 1;
5707 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005708 }
5709
5710 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07005711
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005712 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07005713
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005714 ret_status = hdd_driver_init();
5715 wlan_hdd_inited = ret_status ? 0 : 1;
5716 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005717}
5718
Jeff Johnson295189b2012-06-20 16:38:30 -07005719/**---------------------------------------------------------------------------
5720
Jeff Johnson76052702013-04-16 13:55:05 -07005721 \brief fwpath_changed_handler() - Handler Function
5722
5723 Handle changes to the fwpath parameter
5724
5725 \return - 0 for success, non zero for failure
5726
5727 --------------------------------------------------------------------------*/
5728static int fwpath_changed_handler(const char *kmessage,
5729 struct kernel_param *kp)
5730{
5731 int ret;
5732
5733 ret = param_set_copystring(kmessage, kp);
5734 if (0 == ret)
5735 ret = kickstart_driver();
5736 return ret;
5737}
5738
5739/**---------------------------------------------------------------------------
5740
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005741 \brief con_mode_handler() -
5742
5743 Handler function for module param con_mode when it is changed by userspace
5744 Dynamically linked - do nothing
5745 Statically linked - exit and init driver, as in rmmod and insmod
5746
Jeff Johnson76052702013-04-16 13:55:05 -07005747 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005748
Jeff Johnson76052702013-04-16 13:55:05 -07005749 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005750
5751 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07005752static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005753{
Jeff Johnson76052702013-04-16 13:55:05 -07005754 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005755
Jeff Johnson76052702013-04-16 13:55:05 -07005756 ret = param_set_int(kmessage, kp);
5757 if (0 == ret)
5758 ret = kickstart_driver();
5759 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005760}
5761#endif /* #ifdef MODULE */
5762
5763/**---------------------------------------------------------------------------
5764
Jeff Johnson295189b2012-06-20 16:38:30 -07005765 \brief hdd_get_conparam() -
5766
5767 This is the driver exit point (invoked when module is unloaded using rmmod)
5768
5769 \param - None
5770
5771 \return - tVOS_CON_MODE
5772
5773 --------------------------------------------------------------------------*/
5774tVOS_CON_MODE hdd_get_conparam ( void )
5775{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005776#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07005777 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005778#else
5779 return (tVOS_CON_MODE)curr_con_mode;
5780#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005781}
5782void hdd_set_conparam ( v_UINT_t newParam )
5783{
5784 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005785#ifndef MODULE
5786 curr_con_mode = con_mode;
5787#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005788}
5789/**---------------------------------------------------------------------------
5790
5791 \brief hdd_softap_sta_deauth() - function
5792
5793 This to take counter measure to handle deauth req from HDD
5794
5795 \param - pAdapter - Pointer to the HDD
5796
5797 \param - enable - boolean value
5798
5799 \return - None
5800
5801 --------------------------------------------------------------------------*/
5802
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005803VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07005804{
Jeff Johnson295189b2012-06-20 16:38:30 -07005805 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005806 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07005807
5808 ENTER();
5809
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305810 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07005811
5812 //Ignore request to deauth bcmc station
5813 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005814 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005815
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005816 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07005817
5818 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005819 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005820}
5821
5822/**---------------------------------------------------------------------------
5823
5824 \brief hdd_softap_sta_disassoc() - function
5825
5826 This to take counter measure to handle deauth req from HDD
5827
5828 \param - pAdapter - Pointer to the HDD
5829
5830 \param - enable - boolean value
5831
5832 \return - None
5833
5834 --------------------------------------------------------------------------*/
5835
5836void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
5837{
5838 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5839
5840 ENTER();
5841
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305842 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07005843
5844 //Ignore request to disassoc bcmc station
5845 if( pDestMacAddress[0] & 0x1 )
5846 return;
5847
5848 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
5849}
5850
5851void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
5852{
5853 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5854
5855 ENTER();
5856
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305857 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07005858
5859 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
5860}
5861
Jeff Johnson295189b2012-06-20 16:38:30 -07005862/**---------------------------------------------------------------------------
5863 *
5864 * \brief hdd_get__concurrency_mode() -
5865 *
5866 *
5867 * \param - None
5868 *
5869 * \return - CONCURRENCY MODE
5870 *
5871 * --------------------------------------------------------------------------*/
5872tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
5873{
5874 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5875 hdd_context_t *pHddCtx;
5876
5877 if (NULL != pVosContext)
5878 {
5879 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5880 if (NULL != pHddCtx)
5881 {
5882 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
5883 }
5884 }
5885
5886 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005887 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005888 return VOS_STA;
5889}
5890
5891/* Decide whether to allow/not the apps power collapse.
5892 * Allow apps power collapse if we are in connected state.
5893 * if not, allow only if we are in IMPS */
5894v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
5895{
5896 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08005897 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005898 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07005899 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5900 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5901 hdd_adapter_t *pAdapter = NULL;
5902 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08005903 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005904
Jeff Johnson295189b2012-06-20 16:38:30 -07005905 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5906 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005907
Yathish9f22e662012-12-10 14:21:35 -08005908 concurrent_state = hdd_get_concurrency_mode();
5909
5910#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5911 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
5912 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
5913 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
5914 return TRUE;
5915#endif
5916
Jeff Johnson295189b2012-06-20 16:38:30 -07005917 /*loop through all adapters. TBD fix for Concurrency */
5918 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5919 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5920 {
5921 pAdapter = pAdapterNode->pAdapter;
5922 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
5923 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5924 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005925 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07005926 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08005927 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005928 (eANI_BOOLEAN_TRUE == scanRspPending) ||
5929 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07005930 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005931 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005932 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
5933 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07005934 return FALSE;
5935 }
5936 }
5937 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5938 pAdapterNode = pNext;
5939 }
5940 return TRUE;
5941}
5942
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08005943/* Decides whether to send suspend notification to Riva
5944 * if any adapter is in BMPS; then it is required */
5945v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
5946{
5947 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
5948 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5949
5950 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
5951 {
5952 return TRUE;
5953 }
5954 return FALSE;
5955}
5956
Jeff Johnson295189b2012-06-20 16:38:30 -07005957void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5958{
5959 switch(mode)
5960 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005961 case VOS_STA_MODE:
5962 case VOS_P2P_CLIENT_MODE:
5963 case VOS_P2P_GO_MODE:
5964 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07005965 pHddCtx->concurrency_mode |= (1 << mode);
5966 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07005967 break;
5968 default:
5969 break;
5970
5971 }
5972 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5973 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5974}
5975
5976
5977void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5978{
5979 switch(mode)
5980 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005981 case VOS_STA_MODE:
5982 case VOS_P2P_CLIENT_MODE:
5983 case VOS_P2P_GO_MODE:
5984 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005985 pHddCtx->no_of_sessions[mode]--;
5986 if (!(pHddCtx->no_of_sessions[mode]))
5987 pHddCtx->concurrency_mode &= (~(1 << mode));
5988 break;
5989 default:
5990 break;
5991 }
5992 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5993 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5994}
5995
Jeff Johnsone7245742012-09-05 17:12:55 -07005996/**---------------------------------------------------------------------------
5997 *
5998 * \brief wlan_hdd_restart_init
5999 *
6000 * This function initalizes restart timer/flag. An internal function.
6001 *
6002 * \param - pHddCtx
6003 *
6004 * \return - None
6005 *
6006 * --------------------------------------------------------------------------*/
6007
6008static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6009{
6010 /* Initialize */
6011 pHddCtx->hdd_restart_retries = 0;
6012 atomic_set(&pHddCtx->isRestartInProgress, 0);
6013 vos_timer_init(&pHddCtx->hdd_restart_timer,
6014 VOS_TIMER_TYPE_SW,
6015 wlan_hdd_restart_timer_cb,
6016 pHddCtx);
6017}
6018/**---------------------------------------------------------------------------
6019 *
6020 * \brief wlan_hdd_restart_deinit
6021 *
6022 * This function cleans up the resources used. An internal function.
6023 *
6024 * \param - pHddCtx
6025 *
6026 * \return - None
6027 *
6028 * --------------------------------------------------------------------------*/
6029
6030static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6031{
6032
6033 VOS_STATUS vos_status;
6034 /* Block any further calls */
6035 atomic_set(&pHddCtx->isRestartInProgress, 1);
6036 /* Cleanup */
6037 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6038 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006039 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006040 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6041 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006042 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006043
6044}
6045
6046/**---------------------------------------------------------------------------
6047 *
6048 * \brief wlan_hdd_framework_restart
6049 *
6050 * This function uses a cfg80211 API to start a framework initiated WLAN
6051 * driver module unload/load.
6052 *
6053 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6054 *
6055 *
6056 * \param - pHddCtx
6057 *
6058 * \return - VOS_STATUS_SUCCESS: Success
6059 * VOS_STATUS_E_EMPTY: Adapter is Empty
6060 * VOS_STATUS_E_NOMEM: No memory
6061
6062 * --------------------------------------------------------------------------*/
6063
6064static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6065{
6066 VOS_STATUS status = VOS_STATUS_SUCCESS;
6067 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Yue Ma54db3d42013-04-19 16:44:28 -07006068 unsigned char restart_notification[MAX_RESTART_DRIVER_EVENT_LENGTH + 1];
6069 union iwreq_data wrqu;
Jeff Johnsone7245742012-09-05 17:12:55 -07006070
6071 /* Iterate over all adapters/devices */
6072 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6073 do
6074 {
6075 if( (status == VOS_STATUS_SUCCESS) &&
6076 pAdapterNode &&
6077 pAdapterNode->pAdapter)
6078 {
6079 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6080 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6081 pAdapterNode->pAdapter->dev->name,
6082 pAdapterNode->pAdapter->device_mode,
6083 pHddCtx->hdd_restart_retries + 1);
Yue Ma54db3d42013-04-19 16:44:28 -07006084
6085 /* Notify the wpa supplicant of wcnss restart by sending the custom event */
6086 memset(&wrqu, 0 , sizeof(wrqu));
6087 memset(restart_notification, 0, sizeof(restart_notification));
6088
6089 strlcpy(restart_notification, "QCOM: RESTART_DRIVER_DXE", sizeof(restart_notification));
6090
6091 wrqu.data.pointer = restart_notification;
6092 wrqu.data.length = strlen(restart_notification);
6093
6094 wireless_send_event(pAdapterNode->pAdapter->dev, IWEVCUSTOM, &wrqu, restart_notification);
Jeff Johnsone7245742012-09-05 17:12:55 -07006095 }
6096 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6097 pAdapterNode = pNext;
6098 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6099
Jeff Johnsone7245742012-09-05 17:12:55 -07006100 /* Retry until we unload or reach max count */
6101 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6102 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6103
6104 return status;
6105
6106}
6107/**---------------------------------------------------------------------------
6108 *
6109 * \brief wlan_hdd_restart_timer_cb
6110 *
6111 * Restart timer callback. An internal function.
6112 *
6113 * \param - User data:
6114 *
6115 * \return - None
6116 *
6117 * --------------------------------------------------------------------------*/
6118
6119void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6120{
6121 hdd_context_t *pHddCtx = usrDataForCallback;
6122 wlan_hdd_framework_restart(pHddCtx);
6123 return;
6124
6125}
6126
6127
6128/**---------------------------------------------------------------------------
6129 *
6130 * \brief wlan_hdd_restart_driver
6131 *
6132 * This function sends an event to supplicant to restart the WLAN driver.
6133 *
6134 * This function is called from vos_wlanRestart.
6135 *
6136 * \param - pHddCtx
6137 *
6138 * \return - VOS_STATUS_SUCCESS: Success
6139 * VOS_STATUS_E_EMPTY: Adapter is Empty
6140 * VOS_STATUS_E_ALREADY: Request already in progress
6141
6142 * --------------------------------------------------------------------------*/
6143VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6144{
6145 VOS_STATUS status = VOS_STATUS_SUCCESS;
6146
6147 /* A tight check to make sure reentrancy */
6148 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6149 {
6150 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6151 "%s: WLAN restart is already in progress", __func__);
6152
6153 return VOS_STATUS_E_ALREADY;
6154 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006155 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006156#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006157 wcnss_reset_intr();
6158#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006159
Jeff Johnsone7245742012-09-05 17:12:55 -07006160 return status;
6161}
6162
6163
Jeff Johnson295189b2012-06-20 16:38:30 -07006164//Register the module init/exit functions
6165module_init(hdd_module_init);
6166module_exit(hdd_module_exit);
6167
6168MODULE_LICENSE("Dual BSD/GPL");
6169MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6170MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6171
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006172module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6173 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006174
Jeff Johnson76052702013-04-16 13:55:05 -07006175module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006176 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);