blob: 12ca67feb89b036f7a443effe4e37d9df723b254 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/*========================================================================
43
44 \file wlan_hdd_main.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
54/**=========================================================================
55
56 EDIT HISTORY FOR FILE
57
58
59 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
61
62
63 $Header:$ $DateTime: $ $Author: $
64
65
66 when who what, where, why
67 -------- --- --------------------------------------------------------
68 04/5/09 Shailender Created module.
69 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
70 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
71 ==========================================================================*/
72
73/*--------------------------------------------------------------------------
74 Include Files
75 ------------------------------------------------------------------------*/
76//#include <wlan_qct_driver.h>
77#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070078#include <vos_api.h>
79#include <vos_sched.h>
80#include <vos_power.h>
81#include <linux/etherdevice.h>
82#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070083#ifdef ANI_BUS_TYPE_PLATFORM
84#include <linux/wcnss_wlan.h>
85#endif //ANI_BUS_TYPE_PLATFORM
86#ifdef ANI_BUS_TYPE_PCI
87#include "wcnss_wlan.h"
88#endif /* ANI_BUS_TYPE_PCI */
89#include <wlan_hdd_tx_rx.h>
90#include <palTimer.h>
91#include <wniApi.h>
92#include <wlan_nlink_srv.h>
93#include <wlan_btc_svc.h>
94#include <wlan_hdd_cfg.h>
95#include <wlan_ptt_sock_svc.h>
96#include <wlan_hdd_wowl.h>
97#include <wlan_hdd_misc.h>
98#include <wlan_hdd_wext.h>
99#ifdef WLAN_BTAMP_FEATURE
100#include <bap_hdd_main.h>
101#include <bapInternal.h>
102#endif // WLAN_BTAMP_FEATURE
103
Jeff Johnson295189b2012-06-20 16:38:30 -0700104#include <linux/wireless.h>
105#include <net/cfg80211.h>
106#include "wlan_hdd_cfg80211.h"
107#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700108#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700109int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include "sapApi.h"
111#include <linux/semaphore.h>
112#include <mach/subsystem_restart.h>
113#include <wlan_hdd_hostapd.h>
114#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700115#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700116#include "wlan_hdd_dev_pwr.h"
117#ifdef WLAN_BTAMP_FEATURE
118#include "bap_hdd_misc.h"
119#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700120#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700121#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800122#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530123#ifdef FEATURE_WLAN_TDLS
124#include "wlan_hdd_tdls.h"
125#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700126
127#ifdef MODULE
128#define WLAN_MODULE_NAME module_name(THIS_MODULE)
129#else
130#define WLAN_MODULE_NAME "wlan"
131#endif
132
133#ifdef TIMER_MANAGER
134#define TIMER_MANAGER_STR " +TIMER_MANAGER"
135#else
136#define TIMER_MANAGER_STR ""
137#endif
138
139#ifdef MEMORY_DEBUG
140#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
141#else
142#define MEMORY_DEBUG_STR ""
143#endif
144
145/* the Android framework expects this param even though we don't use it */
146#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700147static char fwpath_buffer[BUF_LEN];
148static struct kparam_string fwpath = {
149 .string = fwpath_buffer,
150 .maxlen = BUF_LEN,
151};
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700152#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700153static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700154#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700155
Jeff Johnsone7245742012-09-05 17:12:55 -0700156/*
157 * The rate at which the driver sends RESTART event to supplicant
158 * once the function 'vos_wlanRestart()' is called
159 *
160 */
161#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
162#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700163
164/*
165 * Size of Driver command strings from upper layer
166 */
167#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
168#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
169
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800170#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700171static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700172#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700173/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700174static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700175
176//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700177static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
178static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
179static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
180void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800181void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700182
Jeff Johnson295189b2012-06-20 16:38:30 -0700183v_U16_t hdd_select_queue(struct net_device *dev,
184 struct sk_buff *skb);
185
186#ifdef WLAN_FEATURE_PACKET_FILTERING
187static void hdd_set_multicast_list(struct net_device *dev);
188#endif
189
190void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700191int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700192
193extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800194#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
195void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
196static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
197static VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700198static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
199 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
200 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700201static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
202 tANI_U8 *pTargetApBssid,
203 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800204#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700205static int hdd_netdev_notifier_call(struct notifier_block * nb,
206 unsigned long state,
207 void *ndev)
208{
209 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700210 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700211 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700212#ifdef WLAN_BTAMP_FEATURE
213 VOS_STATUS status;
214 hdd_context_t *pHddCtx;
215#endif
216
217 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700218 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700219 (strncmp(dev->name, "p2p", 3)))
220 return NOTIFY_DONE;
221
222 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700223 return NOTIFY_DONE;
224
Jeff Johnson295189b2012-06-20 16:38:30 -0700225 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700226 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700227
Jeff Johnson27cee452013-03-27 11:10:24 -0700228 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700229 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800230 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700231 VOS_ASSERT(0);
232 return NOTIFY_DONE;
233 }
234
Jeff Johnson27cee452013-03-27 11:10:24 -0700235 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
236 if (NULL == pHddCtx)
237 {
238 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
239 VOS_ASSERT(0);
240 return NOTIFY_DONE;
241 }
242
243 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
244 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700245
246 switch (state) {
247 case NETDEV_REGISTER:
248 break;
249
250 case NETDEV_UNREGISTER:
251 break;
252
253 case NETDEV_UP:
254 break;
255
256 case NETDEV_DOWN:
257 break;
258
259 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700260 if(TRUE == pAdapter->isLinkUpSvcNeeded)
261 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700262 break;
263
264 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700265 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700266 {
267 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800268 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700269 hdd_abort_mac_scan(pAdapter->pHddCtx);
270 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800271 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700272 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
273 if(!result)
274 {
275 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800276 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700277 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700278 }
279 }
280 else
281 {
282 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700283 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700284 }
285#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700286 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700287 status = WLANBAP_StopAmp();
288 if(VOS_STATUS_SUCCESS != status )
289 {
290 pHddCtx->isAmpAllowed = VOS_TRUE;
291 hddLog(VOS_TRACE_LEVEL_FATAL,
292 "%s: Failed to stop AMP", __func__);
293 }
294 else
295 {
296 //a state m/c implementation in PAL is TBD to avoid this delay
297 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700298 if ( pHddCtx->isAmpAllowed )
299 {
300 WLANBAP_DeregisterFromHCI();
301 pHddCtx->isAmpAllowed = VOS_FALSE;
302 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700303 }
304#endif //WLAN_BTAMP_FEATURE
305 break;
306
307 default:
308 break;
309 }
310
311 return NOTIFY_DONE;
312}
313
314struct notifier_block hdd_netdev_notifier = {
315 .notifier_call = hdd_netdev_notifier_call,
316};
317
318/*---------------------------------------------------------------------------
319 * Function definitions
320 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700321void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
322void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700323//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700324static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700325#ifndef MODULE
326/* current con_mode - used only for statically linked driver
327 * con_mode is changed by userspace to indicate a mode change which will
328 * result in calling the module exit and init functions. The module
329 * exit function will clean up based on the value of con_mode prior to it
330 * being changed by userspace. So curr_con_mode records the current con_mode
331 * for exit when con_mode becomes the next mode for init
332 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700333static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700334#endif
335
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800336/**---------------------------------------------------------------------------
337
338 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
339
340 Called immediately after the cfg.ini is read in order to configure
341 the desired trace levels.
342
343 \param - moduleId - module whose trace level is being configured
344 \param - bitmask - bitmask of log levels to be enabled
345
346 \return - void
347
348 --------------------------------------------------------------------------*/
349static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
350{
351 wpt_tracelevel level;
352
353 /* if the bitmask is the default value, then a bitmask was not
354 specified in cfg.ini, so leave the logging level alone (it
355 will remain at the "compiled in" default value) */
356 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
357 {
358 return;
359 }
360
361 /* a mask was specified. start by disabling all logging */
362 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
363
364 /* now cycle through the bitmask until all "set" bits are serviced */
365 level = VOS_TRACE_LEVEL_FATAL;
366 while (0 != bitmask)
367 {
368 if (bitmask & 1)
369 {
370 vos_trace_setValue(moduleId, level, 1);
371 }
372 level++;
373 bitmask >>= 1;
374 }
375}
376
377
Jeff Johnson295189b2012-06-20 16:38:30 -0700378/**---------------------------------------------------------------------------
379
380 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
381
382 Called immediately after the cfg.ini is read in order to configure
383 the desired trace levels in the WDI.
384
385 \param - moduleId - module whose trace level is being configured
386 \param - bitmask - bitmask of log levels to be enabled
387
388 \return - void
389
390 --------------------------------------------------------------------------*/
391static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
392{
393 wpt_tracelevel level;
394
395 /* if the bitmask is the default value, then a bitmask was not
396 specified in cfg.ini, so leave the logging level alone (it
397 will remain at the "compiled in" default value) */
398 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
399 {
400 return;
401 }
402
403 /* a mask was specified. start by disabling all logging */
404 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
405
406 /* now cycle through the bitmask until all "set" bits are serviced */
407 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
408 while (0 != bitmask)
409 {
410 if (bitmask & 1)
411 {
412 wpalTraceSetLevel(moduleId, level, 1);
413 }
414 level++;
415 bitmask >>= 1;
416 }
417}
Jeff Johnson295189b2012-06-20 16:38:30 -0700418
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530419/*
420 * FUNCTION: wlan_hdd_validate_context
421 * This function is used to check the HDD context
422 */
423int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
424{
425 ENTER();
426
427 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
428 {
429 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
430 "%s: HDD context is Null", __func__);
431 return -ENODEV;
432 }
433
434 if (pHddCtx->isLogpInProgress)
435 {
436 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
437 "%s: LOGP in Progress. Ignore!!!", __func__);
438 return -EAGAIN;
439 }
440
441 if (pHddCtx->isLoadUnloadInProgress)
442 {
443 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
444 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
445 return -EAGAIN;
446 }
447 return 0;
448}
449
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530450void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
451{
452 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
453 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
454 hdd_config_t *cfg_param;
455 eCsrPhyMode phyMode;
456
457 if (NULL == pHddCtx)
458 {
459 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
460 "HDD Context is null !!");
461 return ;
462 }
463
464 cfg_param = pHddCtx->cfg_ini;
465
466 if (NULL == cfg_param)
467 {
468 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
469 "cfg_params not available !!");
470 return ;
471 }
472
473 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
474
475 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
476 {
477 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
478 (eCSR_DOT11_MODE_11ac == phyMode) ||
479 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
480 {
481 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
482 "Setting phymode to 11n!!");
483 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
484 }
485 }
486 else
487 {
488 /*New country Supports 11ac as well resetting value back from .ini*/
489 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
490 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
491 return ;
492 }
493
494 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
495 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
496 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
497 {
498 VOS_STATUS vosStatus;
499
500 // need to issue a disconnect to CSR.
501 INIT_COMPLETION(pAdapter->disconnect_comp_var);
502 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
503 pAdapter->sessionId,
504 eCSR_DISCONNECT_REASON_UNSPECIFIED );
505
506 if (VOS_STATUS_SUCCESS == vosStatus)
507 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
508 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
509
510 }
511}
512
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700513void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
514{
515 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
516 hdd_config_t *cfg_param;
517
518 if (NULL == pHddCtx)
519 {
520 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
521 "HDD Context is null !!");
522 return ;
523 }
524
525 cfg_param = pHddCtx->cfg_ini;
526
527 if (NULL == cfg_param)
528 {
529 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
530 "cfg_params not available !!");
531 return ;
532 }
533
534 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
535 {
536 /*New country doesn't support DFS */
537 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
538 }
539 else
540 {
541 /*New country Supports DFS as well resetting value back from .ini*/
542 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
543 }
544
545}
546
Jeff Johnson295189b2012-06-20 16:38:30 -0700547int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
548{
549 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
550 hdd_priv_data_t priv_data;
551 tANI_U8 *command = NULL;
552 int ret = 0;
553
554 if (NULL == pAdapter)
555 {
556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700557 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700558 ret = -ENODEV;
559 goto exit;
560 }
561
Jeff Johnsone7245742012-09-05 17:12:55 -0700562 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700563 {
564 ret = -EINVAL;
565 goto exit;
566 }
567
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -0700568 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
569 {
570 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
571 "%s:LOGP in Progress. Ignore!!!", __func__);
572 ret = -EBUSY;
573 goto exit;
574 }
575
Jeff Johnson295189b2012-06-20 16:38:30 -0700576 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
577 {
578 ret = -EFAULT;
579 goto exit;
580 }
581
582 command = kmalloc(priv_data.total_len, GFP_KERNEL);
583 if (!command)
584 {
585 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700586 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700587 ret = -ENOMEM;
588 goto exit;
589 }
590
591 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
592 {
593 ret = -EFAULT;
594 goto exit;
595 }
596
597 if ((SIOCDEVPRIVATE + 1) == cmd)
598 {
599 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
600
601 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700602 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700603
604 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
605 {
606 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
607 sizeof(tSirMacAddr)))
608 {
609 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700610 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700611 ret = -EFAULT;
612 }
613 }
Amar Singhal0974e402013-02-12 14:27:46 -0800614 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700615 {
Amar Singhal0974e402013-02-12 14:27:46 -0800616 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700617 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800618
Jeff Johnson295189b2012-06-20 16:38:30 -0700619 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800620
621 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700622 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700623 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800624 "%s: SetBandCommand Info comm %s UL %d, TL %d", __func__, command, priv_data.used_len, priv_data.total_len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700625 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800626 ret = hdd_setBand_helper(dev, ptr);
627 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700628 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
629 {
630 char *country_code;
631
632 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700633
634 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530635 hdd_checkandupdate_phymode(pAdapter, country_code);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700636 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
Gopichand Nakkalaacd94112013-05-29 21:37:47 +0530637 pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700638 if( 0 != ret )
639 {
640 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
641 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
642
643 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700644 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800645#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
646 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
647 {
648 tANI_U8 *value = command;
649 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
650 tANI_U8 revision = 0;
651 eHalStatus status = eHAL_STATUS_SUCCESS;
652 v_REGDOMAIN_t regId;
653
654 status = hdd_parse_countryrev(value, countryCode, &revision);
655 if (eHAL_STATUS_SUCCESS != status)
656 {
657 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
658 "%s: Failed to parse country revision information", __func__);
659 ret = -EINVAL;
660 goto exit;
661 }
662
663 /* Validate country code */
664 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
665 if (eHAL_STATUS_SUCCESS != status)
666 {
667 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
668 "%s: Invalid country code %s", __func__, countryCode);
669 ret = -EINVAL;
670 goto exit;
671 }
672
673 /* Validate revision */
674 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
675 {
676 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
677 "%s: Invalid revision %d", __func__, revision);
678 ret = -EINVAL;
679 goto exit;
680 }
681
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700682 hdd_checkandupdate_dfssetting(pAdapter, countryCode);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530683 hdd_checkandupdate_phymode(pAdapter, countryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800684 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
Gopichand Nakkalaacd94112013-05-29 21:37:47 +0530685 pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800686 if (0 != ret)
687 {
688 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
689 "%s: SME Change Country code fail ret=%d", __func__, ret);
690 ret = -EINVAL;
691 goto exit;
692 }
693
694 if (0 == strncmp(countryCode, "KR", 2))
695 {
696 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
697 revision);
698 if (eHAL_STATUS_SUCCESS != status)
699 {
700 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
701 "%s: Failed to build valid channel list", __func__);
702 ret = -EINVAL;
703 goto exit;
704 }
705 }
706 }
707#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700708 /*
709 command should be a string having format
710 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
711 */
Amar Singhal0974e402013-02-12 14:27:46 -0800712 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700713 {
Amar Singhal0974e402013-02-12 14:27:46 -0800714 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700715
716 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700717 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700718
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800719 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700720 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800721 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
722 {
723 int suspend = 0;
724 tANI_U8 *ptr = (tANI_U8*)command + 15;
725
726 suspend = *ptr - '0';
727 hdd_set_wlan_suspend_mode(suspend);
728 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800729#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
730 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
731 {
732 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700733 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800734 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
735 eHalStatus status = eHAL_STATUS_SUCCESS;
736
737 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
738 value = value + 15;
739
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700740 /* Convert the value from ascii to integer */
741 ret = kstrtos8(value, 10, &rssi);
742 if (ret < 0)
743 {
744 /* If the input value is greater than max value of datatype, then also
745 kstrtou8 fails */
746 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
747 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
748 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
749 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
750 ret = -EINVAL;
751 goto exit;
752 }
753
Srinivas Girigowdade697412013-02-14 16:31:48 -0800754 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700755
Srinivas Girigowdade697412013-02-14 16:31:48 -0800756 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
757 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
758 {
759 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
760 "Neighbor lookup threshold value %d is out of range"
761 " (Min: %d Max: %d)", lookUpThreshold,
762 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
763 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
764 ret = -EINVAL;
765 goto exit;
766 }
767
768 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
769 "%s: Received Command to Set Roam trigger"
770 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
771
772 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
773 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
774 if (eHAL_STATUS_SUCCESS != status)
775 {
776 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
777 "%s: Failed to set roam trigger, try again", __func__);
778 ret = -EPERM;
779 goto exit;
780 }
781
782 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
783 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
784 }
785 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
786 {
787 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
788 int rssi = (-1) * lookUpThreshold;
789 char extra[32];
790 tANI_U8 len = 0;
791
792 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
793 if (copy_to_user(priv_data.buf, &extra, len + 1))
794 {
795 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
796 "%s: failed to copy data to user buffer", __func__);
797 ret = -EFAULT;
798 goto exit;
799 }
800 }
801 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
802 {
803 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700804 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700805 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700806
Srinivas Girigowdade697412013-02-14 16:31:48 -0800807 /* input refresh period is in terms of seconds */
808 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
809 value = value + 18;
810 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700811 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800812 if (ret < 0)
813 {
814 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700815 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800816 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700817 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -0800818 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700819 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
820 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800821 ret = -EINVAL;
822 goto exit;
823 }
824
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700825 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
826 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800827 {
828 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700829 "Roam scan period value %d is out of range"
830 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700831 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
832 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800833 ret = -EINVAL;
834 goto exit;
835 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700836 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800837
838 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
839 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700840 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800841
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700842 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
843 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800844 }
845 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
846 {
847 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
848 char extra[32];
849 tANI_U8 len = 0;
850
851 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
852 /* Returned value is in units of seconds */
853 if (copy_to_user(priv_data.buf, &extra, len + 1))
854 {
855 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
856 "%s: failed to copy data to user buffer", __func__);
857 ret = -EFAULT;
858 goto exit;
859 }
860 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700861 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
862 {
863 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700864 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700865 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700866
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700867 /* input refresh period is in terms of seconds */
868 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
869 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700870
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700871 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700872 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700873 if (ret < 0)
874 {
875 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700876 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700877 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700878 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700879 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700880 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
881 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
882 ret = -EINVAL;
883 goto exit;
884 }
885
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700886 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
887 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
888 {
889 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
890 "Neighbor scan results refresh period value %d is out of range"
891 " (Min: %d Max: %d)", roamScanRefreshPeriod,
892 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
893 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
894 ret = -EINVAL;
895 goto exit;
896 }
897 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
898
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
900 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -0700901 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700902
903 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
904 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
905 }
906 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
907 {
908 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
909 char extra[32];
910 tANI_U8 len = 0;
911
912 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
913 /* Returned value is in units of seconds */
914 if (copy_to_user(priv_data.buf, &extra, len + 1))
915 {
916 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
917 "%s: failed to copy data to user buffer", __func__);
918 ret = -EFAULT;
919 goto exit;
920 }
921 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700922#ifdef FEATURE_WLAN_LFR
923 /* SETROAMMODE */
924 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
925 {
926 tANI_U8 *value = command;
927 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
928
929 /* Move pointer to ahead of SETROAMMODE<delimiter> */
930 value = value + SIZE_OF_SETROAMMODE + 1;
931
932 /* Convert the value from ascii to integer */
933 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
934 if (ret < 0)
935 {
936 /* If the input value is greater than max value of datatype, then also
937 kstrtou8 fails */
938 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
939 "%s: kstrtou8 failed range [%d - %d]", __func__,
940 CFG_LFR_FEATURE_ENABLED_MIN,
941 CFG_LFR_FEATURE_ENABLED_MAX);
942 ret = -EINVAL;
943 goto exit;
944 }
945 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
946 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
947 {
948 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
949 "Roam Mode value %d is out of range"
950 " (Min: %d Max: %d)", roamMode,
951 CFG_LFR_FEATURE_ENABLED_MIN,
952 CFG_LFR_FEATURE_ENABLED_MAX);
953 ret = -EINVAL;
954 goto exit;
955 }
956
957 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
958 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
959 /*
960 * Note that
961 * SETROAMMODE 0 is to enable LFR while
962 * SETROAMMODE 1 is to disable LFR, but
963 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
964 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
965 */
966 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
967 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
968 else
969 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
970
971 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
972 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
973 }
974 /* GETROAMMODE */
975 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
976 {
977 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
978 char extra[32];
979 tANI_U8 len = 0;
980
981 /*
982 * roamMode value shall be inverted because the sementics is different.
983 */
984 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
985 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
986 else
987 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
988
989 len = snprintf(extra, sizeof(extra), "%s %d", command, roamMode);
990 if (copy_to_user(priv_data.buf, &extra, len + 1))
991 {
992 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
993 "%s: failed to copy data to user buffer", __func__);
994 ret = -EFAULT;
995 goto exit;
996 }
997 }
998#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -0800999#endif
1000#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1001 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
1002 {
1003 tANI_U8 *value = command;
1004 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
1005
1006 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
1007 value = value + 13;
1008 /* Convert the value from ascii to integer */
1009 ret = kstrtou8(value, 10, &roamRssiDiff);
1010 if (ret < 0)
1011 {
1012 /* If the input value is greater than max value of datatype, then also
1013 kstrtou8 fails */
1014 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1015 "%s: kstrtou8 failed range [%d - %d]", __func__,
1016 CFG_ROAM_RSSI_DIFF_MIN,
1017 CFG_ROAM_RSSI_DIFF_MAX);
1018 ret = -EINVAL;
1019 goto exit;
1020 }
1021
1022 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
1023 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
1024 {
1025 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1026 "Roam rssi diff value %d is out of range"
1027 " (Min: %d Max: %d)", roamRssiDiff,
1028 CFG_ROAM_RSSI_DIFF_MIN,
1029 CFG_ROAM_RSSI_DIFF_MAX);
1030 ret = -EINVAL;
1031 goto exit;
1032 }
1033
1034 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1035 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
1036
1037 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
1038 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
1039 }
1040 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
1041 {
1042 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
1043 char extra[32];
1044 tANI_U8 len = 0;
1045
1046 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
1047 if (copy_to_user(priv_data.buf, &extra, len + 1))
1048 {
1049 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1050 "%s: failed to copy data to user buffer", __func__);
1051 ret = -EFAULT;
1052 goto exit;
1053 }
1054 }
1055#endif
1056#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1057 else if (strncmp(command, "GETBAND", 7) == 0)
1058 {
1059 int band = -1;
1060 char extra[32];
1061 tANI_U8 len = 0;
1062 hdd_getBand_helper(pHddCtx, &band);
1063
1064 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
1065 if (copy_to_user(priv_data.buf, &extra, len + 1))
1066 {
1067 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1068 "%s: failed to copy data to user buffer", __func__);
1069 ret = -EFAULT;
1070 goto exit;
1071 }
1072 }
1073 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
1074 {
1075 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
1076 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
1077 tANI_U8 revision = 0;
1078 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
1079 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
1080 char extra[32] = {0};
1081 tANI_U8 len = 0;
1082
1083 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
1084 {
1085 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1086 "%s: failed to get country code", __func__);
1087 ret = -EFAULT;
1088 goto exit;
1089 }
1090 pBuf[uBufLen] = '\0';
1091 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
1092
1093 if (0 == strncmp(pBuf, "KR", 2))
1094 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
1095 else
1096 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
1097
1098 if (copy_to_user(priv_data.buf, &extra, len + 1))
1099 {
1100 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1101 "%s: failed to copy data to user buffer", __func__);
1102 ret = -EFAULT;
1103 goto exit;
1104 }
1105 }
1106 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1107 {
1108 tANI_U8 *value = command;
1109 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1110 tANI_U8 numChannels = 0;
1111 eHalStatus status = eHAL_STATUS_SUCCESS;
1112
1113 status = hdd_parse_channellist(value, ChannelList, &numChannels);
1114 if (eHAL_STATUS_SUCCESS != status)
1115 {
1116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1117 "%s: Failed to parse channel list information", __func__);
1118 ret = -EINVAL;
1119 goto exit;
1120 }
1121
1122 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
1123 {
1124 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1125 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
1126 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
1127 ret = -EINVAL;
1128 goto exit;
1129 }
1130 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
1131 numChannels);
1132 if (eHAL_STATUS_SUCCESS != status)
1133 {
1134 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1135 "%s: Failed to update channel list information", __func__);
1136 ret = -EINVAL;
1137 goto exit;
1138 }
1139 }
1140 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
1141 {
1142 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1143 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07001144 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001145 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07001146 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001147
1148 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
1149 ChannelList, &numChannels ))
1150 {
1151 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1152 "%s: failed to get roam scan channel list", __func__);
1153 ret = -EFAULT;
1154 goto exit;
1155 }
1156 /* output channel list is of the format
1157 [Number of roam scan channels][Channel1][Channel2]... */
1158 /* copy the number of channels in the 0th index */
1159 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
1160 for (j = 0; (j < numChannels); j++)
1161 {
1162 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
1163 }
1164
1165 if (copy_to_user(priv_data.buf, &extra, len + 1))
1166 {
1167 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1168 "%s: failed to copy data to user buffer", __func__);
1169 ret = -EFAULT;
1170 goto exit;
1171 }
1172 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001173 else if (strncmp(command, "GETCCXMODE", 10) == 0)
1174 {
1175 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1176 char extra[32];
1177 tANI_U8 len = 0;
1178
1179 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
1180 if (copy_to_user(priv_data.buf, &extra, len + 1))
1181 {
1182 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1183 "%s: failed to copy data to user buffer", __func__);
1184 ret = -EFAULT;
1185 goto exit;
1186 }
1187 }
1188 else if (strncmp(command, "GETOKCMODE", 10) == 0)
1189 {
1190 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
1191 char extra[32];
1192 tANI_U8 len = 0;
1193
1194 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
1195 if (copy_to_user(priv_data.buf, &extra, len + 1))
1196 {
1197 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1198 "%s: failed to copy data to user buffer", __func__);
1199 ret = -EFAULT;
1200 goto exit;
1201 }
1202 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001203 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001204 {
1205 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1206 char extra[32];
1207 tANI_U8 len = 0;
1208
1209 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
1210 if (copy_to_user(priv_data.buf, &extra, len + 1))
1211 {
1212 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1213 "%s: failed to copy data to user buffer", __func__);
1214 ret = -EFAULT;
1215 goto exit;
1216 }
1217 }
1218 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
1219 {
1220 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1221 char extra[32];
1222 tANI_U8 len = 0;
1223
1224 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
1225 if (copy_to_user(priv_data.buf, &extra, len + 1))
1226 {
1227 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1228 "%s: failed to copy data to user buffer", __func__);
1229 ret = -EFAULT;
1230 goto exit;
1231 }
1232 }
1233 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
1234 {
1235 tANI_U8 *value = command;
1236 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1237
1238 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1239 value = value + 26;
1240 /* Convert the value from ascii to integer */
1241 ret = kstrtou8(value, 10, &minTime);
1242 if (ret < 0)
1243 {
1244 /* If the input value is greater than max value of datatype, then also
1245 kstrtou8 fails */
1246 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1247 "%s: kstrtou8 failed range [%d - %d]", __func__,
1248 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1249 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1250 ret = -EINVAL;
1251 goto exit;
1252 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001253 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1254 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1255 {
1256 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1257 "scan min channel time value %d is out of range"
1258 " (Min: %d Max: %d)", minTime,
1259 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1260 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1261 ret = -EINVAL;
1262 goto exit;
1263 }
1264
1265 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1266 "%s: Received Command to change channel min time = %d", __func__, minTime);
1267
1268 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1269 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1270 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001271 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1272 {
1273 tANI_U8 *value = command;
1274 tANI_U8 channel = 0;
1275 tANI_U8 dwellTime = 0;
1276 tANI_U8 bufLen = 0;
1277 tANI_U8 *buf = NULL;
1278 tSirMacAddr targetApBssid;
1279 eHalStatus status = eHAL_STATUS_SUCCESS;
1280 struct ieee80211_channel chan;
1281 tANI_U8 finalLen = 0;
1282 tANI_U8 *finalBuf = NULL;
1283 tANI_U8 temp = 0;
1284 u64 cookie;
1285 hdd_station_ctx_t *pHddStaCtx = NULL;
1286 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1287
1288 /* if not associated, no need to send action frame */
1289 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1290 {
1291 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1292 ret = -EINVAL;
1293 goto exit;
1294 }
1295
1296 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1297 &dwellTime, &buf, &bufLen);
1298 if (eHAL_STATUS_SUCCESS != status)
1299 {
1300 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1301 "%s: Failed to parse send action frame data", __func__);
1302 ret = -EINVAL;
1303 goto exit;
1304 }
1305
1306 /* if the target bssid is different from currently associated AP,
1307 then no need to send action frame */
1308 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1309 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1310 {
1311 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1312 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001313 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001314 goto exit;
1315 }
1316
1317 /* if the channel number is different from operating channel then
1318 no need to send action frame */
1319 if (channel != pHddStaCtx->conn_info.operationChannel)
1320 {
1321 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1322 "%s: channel(%d) is different from operating channel(%d)",
1323 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1324 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001325 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001326 goto exit;
1327 }
1328 chan.center_freq = sme_ChnToFreq(channel);
1329
1330 finalLen = bufLen + 24;
1331 finalBuf = vos_mem_malloc(finalLen);
1332 if (NULL == finalBuf)
1333 {
1334 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1335 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001336 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001337 goto exit;
1338 }
1339 vos_mem_zero(finalBuf, finalLen);
1340
1341 /* Fill subtype */
1342 temp = SIR_MAC_MGMT_ACTION << 4;
1343 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1344
1345 /* Fill type */
1346 temp = SIR_MAC_MGMT_FRAME;
1347 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1348
1349 /* Fill destination address (bssid of the AP) */
1350 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1351
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001352 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001353 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1354
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07001355 /* Fill BSSID (AP mac address) */
1356 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001357
1358 /* Fill received buffer from 24th address */
1359 vos_mem_copy(finalBuf + 24, buf, bufLen);
1360
Jeff Johnson11c33152013-04-16 17:52:40 -07001361 /* done with the parsed buffer */
1362 vos_mem_free(buf);
1363
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001364 wlan_hdd_action( NULL, dev, &chan, 0, NL80211_CHAN_HT20,
1365 1, dwellTime, finalBuf, finalLen, 1,
1366 1, &cookie );
1367 vos_mem_free(finalBuf);
1368 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001369 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1370 {
1371 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1372 char extra[32];
1373 tANI_U8 len = 0;
1374
1375 /* value is interms of msec */
1376 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1377 if (copy_to_user(priv_data.buf, &extra, len + 1))
1378 {
1379 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1380 "%s: failed to copy data to user buffer", __func__);
1381 ret = -EFAULT;
1382 goto exit;
1383 }
1384 }
1385 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1386 {
1387 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001388 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001389 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001390
1391 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1392 value = value + 19;
1393 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001394 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001395 if (ret < 0)
1396 {
1397 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001398 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001399 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07001400 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001401 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1402 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1403 ret = -EINVAL;
1404 goto exit;
1405 }
1406
1407 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1408 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1409 {
1410 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1411 "lfr mode value %d is out of range"
1412 " (Min: %d Max: %d)", maxTime,
1413 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1414 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1415 ret = -EINVAL;
1416 goto exit;
1417 }
1418
1419 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1420 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1421
1422 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001423
1424 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1425 * where RFS is the RF Switching time. It is twice RFS to consider the
1426 * time to go off channel and return to the home channel. */
1427 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1428 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1429 {
1430 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1431 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1432 " Hence enforcing home away time to disable (0)",
1433 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1434 homeAwayTime = 0;
1435 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1436 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
1437 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001438 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1439 }
1440 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1441 {
1442 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1443 char extra[32];
1444 tANI_U8 len = 0;
1445
1446 /* value is interms of msec */
1447 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1448 if (copy_to_user(priv_data.buf, &extra, len + 1))
1449 {
1450 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1451 "%s: failed to copy data to user buffer", __func__);
1452 ret = -EFAULT;
1453 goto exit;
1454 }
1455 }
1456 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1457 {
1458 tANI_U8 *value = command;
1459 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1460
1461 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1462 value = value + 16;
1463 /* Convert the value from ascii to integer */
1464 ret = kstrtou16(value, 10, &val);
1465 if (ret < 0)
1466 {
1467 /* If the input value is greater than max value of datatype, then also
1468 kstrtou16 fails */
1469 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1470 "%s: kstrtou16 failed range [%d - %d]", __func__,
1471 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1472 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1473 ret = -EINVAL;
1474 goto exit;
1475 }
1476
1477 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1478 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1479 {
1480 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1481 "scan home time value %d is out of range"
1482 " (Min: %d Max: %d)", val,
1483 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1484 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1485 ret = -EINVAL;
1486 goto exit;
1487 }
1488
1489 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1490 "%s: Received Command to change scan home time = %d", __func__, val);
1491
1492 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1493 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1494 }
1495 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1496 {
1497 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1498 char extra[32];
1499 tANI_U8 len = 0;
1500
1501 /* value is interms of msec */
1502 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1503 if (copy_to_user(priv_data.buf, &extra, len + 1))
1504 {
1505 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1506 "%s: failed to copy data to user buffer", __func__);
1507 ret = -EFAULT;
1508 goto exit;
1509 }
1510 }
1511 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1512 {
1513 tANI_U8 *value = command;
1514 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1515
1516 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1517 value = value + 17;
1518 /* Convert the value from ascii to integer */
1519 ret = kstrtou8(value, 10, &val);
1520 if (ret < 0)
1521 {
1522 /* If the input value is greater than max value of datatype, then also
1523 kstrtou8 fails */
1524 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1525 "%s: kstrtou8 failed range [%d - %d]", __func__,
1526 CFG_ROAM_INTRA_BAND_MIN,
1527 CFG_ROAM_INTRA_BAND_MAX);
1528 ret = -EINVAL;
1529 goto exit;
1530 }
1531
1532 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1533 (val > CFG_ROAM_INTRA_BAND_MAX))
1534 {
1535 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1536 "intra band mode value %d is out of range"
1537 " (Min: %d Max: %d)", val,
1538 CFG_ROAM_INTRA_BAND_MIN,
1539 CFG_ROAM_INTRA_BAND_MAX);
1540 ret = -EINVAL;
1541 goto exit;
1542 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001543 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1544 "%s: Received Command to change intra band = %d", __func__, val);
1545
1546 pHddCtx->cfg_ini->nRoamIntraBand = val;
1547 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1548 }
1549 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1550 {
1551 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1552 char extra[32];
1553 tANI_U8 len = 0;
1554
1555 /* value is interms of msec */
1556 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1557 if (copy_to_user(priv_data.buf, &extra, len + 1))
1558 {
1559 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1560 "%s: failed to copy data to user buffer", __func__);
1561 ret = -EFAULT;
1562 goto exit;
1563 }
1564 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001565 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
1566 {
1567 tANI_U8 *value = command;
1568 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
1569
1570 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
1571 value = value + 15;
1572 /* Convert the value from ascii to integer */
1573 ret = kstrtou8(value, 10, &nProbes);
1574 if (ret < 0)
1575 {
1576 /* If the input value is greater than max value of datatype, then also
1577 kstrtou8 fails */
1578 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1579 "%s: kstrtou8 failed range [%d - %d]", __func__,
1580 CFG_ROAM_SCAN_N_PROBES_MIN,
1581 CFG_ROAM_SCAN_N_PROBES_MAX);
1582 ret = -EINVAL;
1583 goto exit;
1584 }
1585
1586 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
1587 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
1588 {
1589 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1590 "NProbes value %d is out of range"
1591 " (Min: %d Max: %d)", nProbes,
1592 CFG_ROAM_SCAN_N_PROBES_MIN,
1593 CFG_ROAM_SCAN_N_PROBES_MAX);
1594 ret = -EINVAL;
1595 goto exit;
1596 }
1597
1598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1599 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
1600
1601 pHddCtx->cfg_ini->nProbes = nProbes;
1602 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
1603 }
1604 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
1605 {
1606 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
1607 char extra[32];
1608 tANI_U8 len = 0;
1609
1610 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1611 if (copy_to_user(priv_data.buf, &extra, len + 1))
1612 {
1613 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1614 "%s: failed to copy data to user buffer", __func__);
1615 ret = -EFAULT;
1616 goto exit;
1617 }
1618 }
1619 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
1620 {
1621 tANI_U8 *value = command;
1622 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001623 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001624
1625 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
1626 /* input value is in units of msec */
1627 value = value + 20;
1628 /* Convert the value from ascii to integer */
1629 ret = kstrtou16(value, 10, &homeAwayTime);
1630 if (ret < 0)
1631 {
1632 /* If the input value is greater than max value of datatype, then also
1633 kstrtou8 fails */
1634 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1635 "%s: kstrtou8 failed range [%d - %d]", __func__,
1636 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1637 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1638 ret = -EINVAL;
1639 goto exit;
1640 }
1641
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001642 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
1643 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
1644 {
1645 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1646 "homeAwayTime value %d is out of range"
1647 " (Min: %d Max: %d)", homeAwayTime,
1648 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
1649 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
1650 ret = -EINVAL;
1651 goto exit;
1652 }
1653
1654 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1655 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
1656
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07001657 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
1658 * where RFS is the RF Switching time. It is twice RFS to consider the
1659 * time to go off channel and return to the home channel. */
1660 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1661 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
1662 {
1663 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1664 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
1665 " Hence enforcing home away time to disable (0)",
1666 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
1667 homeAwayTime = 0;
1668 }
1669
1670 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
1671 {
1672 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
1673 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
1674 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001675 }
1676 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
1677 {
1678 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
1679 char extra[32];
1680 tANI_U8 len = 0;
1681
1682 len = snprintf(extra, sizeof(extra), "%s %d", command, val);
1683 if (copy_to_user(priv_data.buf, &extra, len + 1))
1684 {
1685 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1686 "%s: failed to copy data to user buffer", __func__);
1687 ret = -EFAULT;
1688 goto exit;
1689 }
1690 }
1691 else if (strncmp(command, "REASSOC", 7) == 0)
1692 {
1693 tANI_U8 *value = command;
1694 tANI_U8 channel = 0;
1695 tSirMacAddr targetApBssid;
1696 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001697#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1698 tCsrHandoffRequest handoffInfo;
1699#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001700 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001701 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1702
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001703 /* if not associated, no need to proceed with reassoc */
1704 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1705 {
1706 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1707 ret = -EINVAL;
1708 goto exit;
1709 }
1710
1711 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
1712 if (eHAL_STATUS_SUCCESS != status)
1713 {
1714 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1715 "%s: Failed to parse reassoc command data", __func__);
1716 ret = -EINVAL;
1717 goto exit;
1718 }
1719
1720 /* if the target bssid is same as currently associated AP,
1721 then no need to proceed with reassoc */
1722 if (VOS_TRUE == vos_mem_compare(targetApBssid,
1723 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1724 {
1725 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
1726 ret = -EINVAL;
1727 goto exit;
1728 }
1729
1730 /* Check channel number is a valid channel number */
1731 if(VOS_STATUS_SUCCESS !=
1732 wlan_hdd_validate_operation_channel(pAdapter, channel))
1733 {
1734 hddLog(VOS_TRACE_LEVEL_ERROR,
1735 "%s: Invalid Channel [%d] \n", __func__, channel);
1736 return -EINVAL;
1737 }
1738
1739 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07001740#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
1741 handoffInfo.channel = channel;
1742 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
1743 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
1744#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07001745 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001746#endif
1747#ifdef FEATURE_WLAN_LFR
1748 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1749 {
1750 tANI_U8 *value = command;
1751 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1752
1753 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1754 value = value + 12;
1755 /* Convert the value from ascii to integer */
1756 ret = kstrtou8(value, 10, &lfrMode);
1757 if (ret < 0)
1758 {
1759 /* If the input value is greater than max value of datatype, then also
1760 kstrtou8 fails */
1761 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1762 "%s: kstrtou8 failed range [%d - %d]", __func__,
1763 CFG_LFR_FEATURE_ENABLED_MIN,
1764 CFG_LFR_FEATURE_ENABLED_MAX);
1765 ret = -EINVAL;
1766 goto exit;
1767 }
1768
1769 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1770 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1771 {
1772 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1773 "lfr mode value %d is out of range"
1774 " (Min: %d Max: %d)", lfrMode,
1775 CFG_LFR_FEATURE_ENABLED_MIN,
1776 CFG_LFR_FEATURE_ENABLED_MAX);
1777 ret = -EINVAL;
1778 goto exit;
1779 }
1780
1781 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1782 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1783
1784 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1785 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1786 }
1787#endif
1788#ifdef WLAN_FEATURE_VOWIFI_11R
1789 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1790 {
1791 tANI_U8 *value = command;
1792 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1793
1794 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1795 value = value + 18;
1796 /* Convert the value from ascii to integer */
1797 ret = kstrtou8(value, 10, &ft);
1798 if (ret < 0)
1799 {
1800 /* If the input value is greater than max value of datatype, then also
1801 kstrtou8 fails */
1802 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1803 "%s: kstrtou8 failed range [%d - %d]", __func__,
1804 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1805 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1806 ret = -EINVAL;
1807 goto exit;
1808 }
1809
1810 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1811 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1812 {
1813 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1814 "ft mode value %d is out of range"
1815 " (Min: %d Max: %d)", ft,
1816 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1817 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1818 ret = -EINVAL;
1819 goto exit;
1820 }
1821
1822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1823 "%s: Received Command to change ft mode = %d", __func__, ft);
1824
1825 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1826 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1827 }
1828#endif
1829#ifdef FEATURE_WLAN_CCX
1830 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1831 {
1832 tANI_U8 *value = command;
1833 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1834
1835 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1836 value = value + 11;
1837 /* Convert the value from ascii to integer */
1838 ret = kstrtou8(value, 10, &ccxMode);
1839 if (ret < 0)
1840 {
1841 /* If the input value is greater than max value of datatype, then also
1842 kstrtou8 fails */
1843 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1844 "%s: kstrtou8 failed range [%d - %d]", __func__,
1845 CFG_CCX_FEATURE_ENABLED_MIN,
1846 CFG_CCX_FEATURE_ENABLED_MAX);
1847 ret = -EINVAL;
1848 goto exit;
1849 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001850 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1851 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1852 {
1853 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1854 "Ccx mode value %d is out of range"
1855 " (Min: %d Max: %d)", ccxMode,
1856 CFG_CCX_FEATURE_ENABLED_MIN,
1857 CFG_CCX_FEATURE_ENABLED_MAX);
1858 ret = -EINVAL;
1859 goto exit;
1860 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001861 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1862 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1863
1864 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1865 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1866 }
1867#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001868 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1869 {
1870 tANI_U8 *value = command;
1871 tANI_BOOLEAN roamScanControl = 0;
1872
1873 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1874 value = value + 19;
1875 /* Convert the value from ascii to integer */
1876 ret = kstrtou8(value, 10, &roamScanControl);
1877 if (ret < 0)
1878 {
1879 /* If the input value is greater than max value of datatype, then also
1880 kstrtou8 fails */
1881 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1882 "%s: kstrtou8 failed ", __func__);
1883 ret = -EINVAL;
1884 goto exit;
1885 }
1886
1887 if (0 != roamScanControl)
1888 {
1889 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1890 "roam scan control invalid value = %d",
1891 roamScanControl);
1892 ret = -EINVAL;
1893 goto exit;
1894 }
1895 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1896 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1897
1898 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1899 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001900#ifdef FEATURE_WLAN_OKC
1901 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1902 {
1903 tANI_U8 *value = command;
1904 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1905
1906 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1907 value = value + 11;
1908 /* Convert the value from ascii to integer */
1909 ret = kstrtou8(value, 10, &okcMode);
1910 if (ret < 0)
1911 {
1912 /* If the input value is greater than max value of datatype, then also
1913 kstrtou8 fails */
1914 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1915 "%s: kstrtou8 failed range [%d - %d]", __func__,
1916 CFG_OKC_FEATURE_ENABLED_MIN,
1917 CFG_OKC_FEATURE_ENABLED_MAX);
1918 ret = -EINVAL;
1919 goto exit;
1920 }
1921
1922 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1923 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1924 {
1925 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1926 "Okc mode value %d is out of range"
1927 " (Min: %d Max: %d)", okcMode,
1928 CFG_OKC_FEATURE_ENABLED_MIN,
1929 CFG_OKC_FEATURE_ENABLED_MAX);
1930 ret = -EINVAL;
1931 goto exit;
1932 }
1933
1934 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1935 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1936
1937 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1938 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001939 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1940 {
1941 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1942 char extra[32];
1943 tANI_U8 len = 0;
1944
1945 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1946 if (copy_to_user(priv_data.buf, &extra, len + 1))
1947 {
1948 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1949 "%s: failed to copy data to user buffer", __func__);
1950 ret = -EFAULT;
1951 goto exit;
1952 }
1953 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001954#endif
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05301955#ifdef WLAN_FEATURE_PACKET_FILTERING
1956 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
1957 {
1958 tANI_U8 filterType = 0;
1959 tANI_U8 *value = command;
1960
1961 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
1962 value = value + 22;
1963
1964 /* Convert the value from ascii to integer */
1965 ret = kstrtou8(value, 10, &filterType);
1966 if (ret < 0)
1967 {
1968 /* If the input value is greater than max value of datatype,
1969 * then also kstrtou8 fails
1970 */
1971 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1972 "%s: kstrtou8 failed range ", __func__);
1973 ret = -EINVAL;
1974 goto exit;
1975 }
1976
1977 if (filterType != 0 && filterType != 1)
1978 {
1979 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1980 "%s: Accepted Values are 0 and 1 ", __func__);
1981 ret = -EINVAL;
1982 goto exit;
1983 }
1984 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
1985 pAdapter->sessionId);
1986 }
1987#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001988 else {
1989 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
1990 __func__, command);
1991 }
1992
Jeff Johnson295189b2012-06-20 16:38:30 -07001993 }
1994exit:
1995 if (command)
1996 {
1997 kfree(command);
1998 }
1999 return ret;
2000}
2001
Srinivas Girigowdade697412013-02-14 16:31:48 -08002002#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2003void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
2004{
2005 eCsrBand band = -1;
2006 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
2007 switch (band)
2008 {
2009 case eCSR_BAND_ALL:
2010 *pBand = WLAN_HDD_UI_BAND_AUTO;
2011 break;
2012
2013 case eCSR_BAND_24:
2014 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
2015 break;
2016
2017 case eCSR_BAND_5G:
2018 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
2019 break;
2020
2021 default:
2022 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
2023 *pBand = -1;
2024 break;
2025 }
2026}
2027
2028/**---------------------------------------------------------------------------
2029
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002030 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
2031
2032 This function parses the send action frame data passed in the format
2033 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
2034
2035 \param - pValue Pointer to input country code revision
2036 \param - pTargetApBssid Pointer to target Ap bssid
2037 \param - pChannel Pointer to the Target AP channel
2038 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
2039 \param - pBuf Pointer to data
2040 \param - pBufLen Pointer to data length
2041
2042 \return - 0 for success non-zero for failure
2043
2044 --------------------------------------------------------------------------*/
2045VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
2046 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
2047{
2048 tANI_U8 *inPtr = pValue;
2049 tANI_U8 *dataEnd;
2050 int tempInt;
2051 int j = 0;
2052 int i = 0;
2053 int v = 0;
2054 tANI_U8 tempBuf[32];
2055 tANI_U8 tempByte = 0;
2056
2057 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2058 /*no argument after the command*/
2059 if (NULL == inPtr)
2060 {
2061 return -EINVAL;
2062 }
2063
2064 /*no space after the command*/
2065 else if (SPACE_ASCII_VALUE != *inPtr)
2066 {
2067 return -EINVAL;
2068 }
2069
2070 /*removing empty spaces*/
2071 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2072
2073 /*no argument followed by spaces*/
2074 if ('\0' == *inPtr)
2075 {
2076 return -EINVAL;
2077 }
2078
2079 /*getting the first argument ie the target AP bssid */
2080 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2081 {
2082 return -EINVAL;
2083 }
2084 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2085 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2086 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2087
2088 /* point to the next argument */
2089 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2090 /*no argument after the command*/
2091 if (NULL == inPtr) return -EINVAL;
2092
2093 /*removing empty spaces*/
2094 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2095
2096 /*no argument followed by spaces*/
2097 if ('\0' == *inPtr)
2098 {
2099 return -EINVAL;
2100 }
2101
2102 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07002103 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002104 v = kstrtos32(tempBuf, 10, &tempInt);
2105 if ( v < 0) return -EINVAL;
2106
2107 *pChannel = tempInt;
2108
2109 /* point to the next argument */
2110 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2111 /*no argument after the command*/
2112 if (NULL == inPtr) return -EINVAL;
2113 /*removing empty spaces*/
2114 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2115
2116 /*no argument followed by spaces*/
2117 if ('\0' == *inPtr)
2118 {
2119 return -EINVAL;
2120 }
2121
2122 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07002123 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002124 v = kstrtos32(tempBuf, 10, &tempInt);
2125 if ( v < 0) return -EINVAL;
2126
2127 *pDwellTime = tempInt;
2128
2129 /* point to the next argument */
2130 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2131 /*no argument after the command*/
2132 if (NULL == inPtr) return -EINVAL;
2133 /*removing empty spaces*/
2134 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2135
2136 /*no argument followed by spaces*/
2137 if ('\0' == *inPtr)
2138 {
2139 return -EINVAL;
2140 }
2141
2142 /* find the length of data */
2143 dataEnd = inPtr;
2144 while(('\0' != *dataEnd) )
2145 {
2146 dataEnd++;
2147 ++(*pBufLen);
2148 }
2149 if ( *pBufLen <= 0) return -EINVAL;
2150
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07002151 /* Allocate the number of bytes based on the number of input characters
2152 whether it is even or odd.
2153 if the number of input characters are even, then we need N/2 byte.
2154 if the number of input characters are odd, then we need do (N+1)/2 to
2155 compensate rounding off.
2156 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
2157 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
2158 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002159 if (NULL == *pBuf)
2160 {
2161 hddLog(VOS_TRACE_LEVEL_FATAL,
2162 "%s: vos_mem_alloc failed ", __func__);
2163 return -EINVAL;
2164 }
2165
2166 /* the buffer received from the upper layer is character buffer,
2167 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
2168 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
2169 and f0 in 3rd location */
2170 for (i = 0, j = 0; j < *pBufLen; j += 2)
2171 {
2172 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
2173 (*pBuf)[i++] = tempByte;
2174 }
2175 *pBufLen = i;
2176 return VOS_STATUS_SUCCESS;
2177}
2178
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002179/**---------------------------------------------------------------------------
2180
Srinivas Girigowdade697412013-02-14 16:31:48 -08002181 \brief hdd_parse_countryrev() - HDD Parse country code revision
2182
2183 This function parses the country code revision passed in the format
2184 SETCOUNTRYREV<space><Country code><space>revision
2185
2186 \param - pValue Pointer to input country code revision
2187 \param - pCountryCode Pointer to local output array to record country code
2188 \param - pRevision Pointer to store revision integer number
2189
2190 \return - 0 for success non-zero for failure
2191
2192 --------------------------------------------------------------------------*/
2193VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
2194{
2195 tANI_U8 *inPtr = pValue;
2196 int tempInt;
2197
2198 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2199 /*no argument after the command*/
2200 if (NULL == inPtr)
2201 {
2202 return -EINVAL;
2203 }
2204
2205 /*no space after the command*/
2206 else if (SPACE_ASCII_VALUE != *inPtr)
2207 {
2208 return -EINVAL;
2209 }
2210
2211 /*removing empty spaces*/
2212 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
2213
2214 /*no argument followed by spaces*/
2215 if ('\0' == *inPtr)
2216 {
2217 return -EINVAL;
2218 }
2219
2220 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07002221 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002222
2223 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2224 "Country code is : %s", pCountryCode);
2225
2226 /*inPtr pointing to the beginning of first space after country code */
2227 inPtr = strpbrk( inPtr, " " );
2228 /*no revision number after the country code argument */
2229 if (NULL == inPtr)
2230 {
2231 return -EINVAL;
2232 }
2233
2234 inPtr++;
2235
2236 /*removing empty space*/
2237 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2238
2239 /*no channel list after the number of channels argument and spaces*/
2240 if (0 == strncmp(pCountryCode, "KR", 2))
2241 {
2242 if ('\0' == *inPtr)
2243 {
2244 return -EINVAL;
2245 }
2246
2247 sscanf(inPtr, "%d", &tempInt);
2248 *pRevision = tempInt;
2249 }
2250 else
2251 {
2252 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2253 "Revision input is required only for Country KR");
2254 return -EINVAL;
2255 }
2256 return VOS_STATUS_SUCCESS;
2257}
2258
2259/**---------------------------------------------------------------------------
2260
2261 \brief hdd_parse_channellist() - HDD Parse channel list
2262
2263 This function parses the channel list passed in the format
2264 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002265 if the Number of channels (N) does not match with the actual number of channels passed
2266 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2267 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2268 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2269 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002270
2271 \param - pValue Pointer to input channel list
2272 \param - ChannelList Pointer to local output array to record channel list
2273 \param - pNumChannels Pointer to number of roam scan channels
2274
2275 \return - 0 for success non-zero for failure
2276
2277 --------------------------------------------------------------------------*/
2278VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2279{
2280 tANI_U8 *inPtr = pValue;
2281 int tempInt;
2282 int j = 0;
2283 int v = 0;
2284 char buf[32];
2285
2286 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2287 /*no argument after the command*/
2288 if (NULL == inPtr)
2289 {
2290 return -EINVAL;
2291 }
2292
2293 /*no space after the command*/
2294 else if (SPACE_ASCII_VALUE != *inPtr)
2295 {
2296 return -EINVAL;
2297 }
2298
2299 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002300 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002301
2302 /*no argument followed by spaces*/
2303 if ('\0' == *inPtr)
2304 {
2305 return -EINVAL;
2306 }
2307
2308 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002309 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002310 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002311 if ((v < 0) ||
2312 (tempInt <= 0) ||
2313 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2314 {
2315 return -EINVAL;
2316 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002317
2318 *pNumChannels = tempInt;
2319
2320 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2321 "Number of channels are: %d", *pNumChannels);
2322
2323 for (j = 0; j < (*pNumChannels); j++)
2324 {
2325 /*inPtr pointing to the beginning of first space after number of channels*/
2326 inPtr = strpbrk( inPtr, " " );
2327 /*no channel list after the number of channels argument*/
2328 if (NULL == inPtr)
2329 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002330 if (0 != j)
2331 {
2332 *pNumChannels = j;
2333 return VOS_STATUS_SUCCESS;
2334 }
2335 else
2336 {
2337 return -EINVAL;
2338 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002339 }
2340
2341 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002342 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002343
2344 /*no channel list after the number of channels argument and spaces*/
2345 if ( '\0' == *inPtr )
2346 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002347 if (0 != j)
2348 {
2349 *pNumChannels = j;
2350 return VOS_STATUS_SUCCESS;
2351 }
2352 else
2353 {
2354 return -EINVAL;
2355 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002356 }
2357
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002358 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002359 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002360 if ((v < 0) ||
2361 (tempInt <= 0) ||
2362 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2363 {
2364 return -EINVAL;
2365 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002366 pChannelList[j] = tempInt;
2367
2368 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2369 "Channel %d added to preferred channel list",
2370 pChannelList[j] );
2371 }
2372
Srinivas Girigowdade697412013-02-14 16:31:48 -08002373 return VOS_STATUS_SUCCESS;
2374}
2375
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002376
2377/**---------------------------------------------------------------------------
2378
2379 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
2380
2381 This function parses the reasoc command data passed in the format
2382 REASSOC<space><bssid><space><channel>
2383
2384 \param - pValue Pointer to input country code revision
2385 \param - pTargetApBssid Pointer to target Ap bssid
2386 \param - pChannel Pointer to the Target AP channel
2387
2388 \return - 0 for success non-zero for failure
2389
2390 --------------------------------------------------------------------------*/
2391VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
2392{
2393 tANI_U8 *inPtr = pValue;
2394 int tempInt;
2395 int v = 0;
2396 tANI_U8 tempBuf[32];
2397
2398 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2399 /*no argument after the command*/
2400 if (NULL == inPtr)
2401 {
2402 return -EINVAL;
2403 }
2404
2405 /*no space after the command*/
2406 else if (SPACE_ASCII_VALUE != *inPtr)
2407 {
2408 return -EINVAL;
2409 }
2410
2411 /*removing empty spaces*/
2412 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2413
2414 /*no argument followed by spaces*/
2415 if ('\0' == *inPtr)
2416 {
2417 return -EINVAL;
2418 }
2419
2420 /*getting the first argument ie the target AP bssid */
2421 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
2422 {
2423 return -EINVAL;
2424 }
2425 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
2426 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
2427 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
2428
2429 /* point to the next argument */
2430 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
2431 /*no argument after the command*/
2432 if (NULL == inPtr) return -EINVAL;
2433
2434 /*removing empty spaces*/
2435 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2436
2437 /*no argument followed by spaces*/
2438 if ('\0' == *inPtr)
2439 {
2440 return -EINVAL;
2441 }
2442
2443 /*getting the next argument ie the channel number */
2444 sscanf(inPtr, "%s ", tempBuf);
2445 v = kstrtos32(tempBuf, 10, &tempInt);
2446 if ( v < 0) return -EINVAL;
2447
2448 *pChannel = tempInt;
2449 return VOS_STATUS_SUCCESS;
2450}
2451
2452#endif
2453
Jeff Johnson295189b2012-06-20 16:38:30 -07002454/**---------------------------------------------------------------------------
2455
2456 \brief hdd_open() - HDD Open function
2457
2458 This is called in response to ifconfig up
2459
2460 \param - dev Pointer to net_device structure
2461
2462 \return - 0 for success non-zero for failure
2463
2464 --------------------------------------------------------------------------*/
2465int hdd_open (struct net_device *dev)
2466{
2467 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2468 hdd_context_t *pHddCtx;
2469 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2470 VOS_STATUS status;
2471 v_BOOL_t in_standby = TRUE;
2472
2473 if (NULL == pAdapter)
2474 {
2475 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002476 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002477 return -ENODEV;
2478 }
2479
2480 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2481 if (NULL == pHddCtx)
2482 {
2483 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002484 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002485 return -ENODEV;
2486 }
2487
2488 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2489 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2490 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002491 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2492 {
2493 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302494 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002495 in_standby = FALSE;
2496 break;
2497 }
2498 else
2499 {
2500 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2501 pAdapterNode = pNext;
2502 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002503 }
2504
2505 if (TRUE == in_standby)
2506 {
2507 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2508 {
2509 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2510 "wlan out of power save", __func__);
2511 return -EINVAL;
2512 }
2513 }
2514
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002515 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002516 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2517 {
2518 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002519 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002520 /* Enable TX queues only when we are connected */
2521 netif_tx_start_all_queues(dev);
2522 }
2523
2524 return 0;
2525}
2526
2527int hdd_mon_open (struct net_device *dev)
2528{
2529 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2530
2531 if(pAdapter == NULL) {
2532 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002533 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002534 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002535 }
2536
2537 netif_start_queue(dev);
2538
2539 return 0;
2540}
2541/**---------------------------------------------------------------------------
2542
2543 \brief hdd_stop() - HDD stop function
2544
2545 This is called in response to ifconfig down
2546
2547 \param - dev Pointer to net_device structure
2548
2549 \return - 0 for success non-zero for failure
2550
2551 --------------------------------------------------------------------------*/
2552
2553int hdd_stop (struct net_device *dev)
2554{
2555 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2556 hdd_context_t *pHddCtx;
2557 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2558 VOS_STATUS status;
2559 v_BOOL_t enter_standby = TRUE;
2560
2561 ENTER();
2562
2563 if (NULL == pAdapter)
2564 {
2565 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002566 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002567 return -ENODEV;
2568 }
2569
2570 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2571 if (NULL == pHddCtx)
2572 {
2573 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002574 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002575 return -ENODEV;
2576 }
2577
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002578 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002579 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2580 netif_tx_disable(pAdapter->dev);
2581 netif_carrier_off(pAdapter->dev);
2582
2583
2584 /* SoftAP ifaces should never go in power save mode
2585 making sure same here. */
2586 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2587 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002588 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002589 )
2590 {
2591 /* SoftAP mode, so return from here */
2592 EXIT();
2593 return 0;
2594 }
2595
2596 /* Find if any iface is up then
2597 if any iface is up then can't put device to sleep/ power save mode. */
2598 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2599 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2600 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002601 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2602 {
2603 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302604 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002605 enter_standby = FALSE;
2606 break;
2607 }
2608 else
2609 {
2610 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2611 pAdapterNode = pNext;
2612 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002613 }
2614
2615 if (TRUE == enter_standby)
2616 {
2617 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2618 "entering standby", __func__);
2619 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2620 {
2621 /*log and return success*/
2622 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2623 "wlan in power save", __func__);
2624 }
2625 }
2626
2627 EXIT();
2628 return 0;
2629}
2630
2631/**---------------------------------------------------------------------------
2632
2633 \brief hdd_uninit() - HDD uninit function
2634
2635 This is called during the netdev unregister to uninitialize all data
2636associated with the device
2637
2638 \param - dev Pointer to net_device structure
2639
2640 \return - void
2641
2642 --------------------------------------------------------------------------*/
2643static void hdd_uninit (struct net_device *dev)
2644{
2645 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2646
2647 ENTER();
2648
2649 do
2650 {
2651 if (NULL == pAdapter)
2652 {
2653 hddLog(VOS_TRACE_LEVEL_FATAL,
2654 "%s: NULL pAdapter", __func__);
2655 break;
2656 }
2657
2658 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2659 {
2660 hddLog(VOS_TRACE_LEVEL_FATAL,
2661 "%s: Invalid magic", __func__);
2662 break;
2663 }
2664
2665 if (NULL == pAdapter->pHddCtx)
2666 {
2667 hddLog(VOS_TRACE_LEVEL_FATAL,
2668 "%s: NULL pHddCtx", __func__);
2669 break;
2670 }
2671
2672 if (dev != pAdapter->dev)
2673 {
2674 hddLog(VOS_TRACE_LEVEL_FATAL,
2675 "%s: Invalid device reference", __func__);
2676 /* we haven't validated all cases so let this go for now */
2677 }
2678
2679 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2680
2681 /* after uninit our adapter structure will no longer be valid */
2682 pAdapter->dev = NULL;
2683 pAdapter->magic = 0;
2684 } while (0);
2685
2686 EXIT();
2687}
2688
2689/**---------------------------------------------------------------------------
2690
2691 \brief hdd_release_firmware() -
2692
2693 This function calls the release firmware API to free the firmware buffer.
2694
2695 \param - pFileName Pointer to the File Name.
2696 pCtx - Pointer to the adapter .
2697
2698
2699 \return - 0 for success, non zero for failure
2700
2701 --------------------------------------------------------------------------*/
2702
2703VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2704{
2705 VOS_STATUS status = VOS_STATUS_SUCCESS;
2706 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2707 ENTER();
2708
2709
2710 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2711
2712 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2713
2714 if(pHddCtx->fw) {
2715 release_firmware(pHddCtx->fw);
2716 pHddCtx->fw = NULL;
2717 }
2718 else
2719 status = VOS_STATUS_E_FAILURE;
2720 }
2721 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2722 if(pHddCtx->nv) {
2723 release_firmware(pHddCtx->nv);
2724 pHddCtx->nv = NULL;
2725 }
2726 else
2727 status = VOS_STATUS_E_FAILURE;
2728
2729 }
2730
2731 EXIT();
2732 return status;
2733}
2734
2735/**---------------------------------------------------------------------------
2736
2737 \brief hdd_request_firmware() -
2738
2739 This function reads the firmware file using the request firmware
2740 API and returns the the firmware data and the firmware file size.
2741
2742 \param - pfileName - Pointer to the file name.
2743 - pCtx - Pointer to the adapter .
2744 - ppfw_data - Pointer to the pointer of the firmware data.
2745 - pSize - Pointer to the file size.
2746
2747 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2748
2749 --------------------------------------------------------------------------*/
2750
2751
2752VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2753{
2754 int status;
2755 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2756 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2757 ENTER();
2758
2759 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2760
2761 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2762
2763 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2764 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2765 __func__, pfileName);
2766 retval = VOS_STATUS_E_FAILURE;
2767 }
2768
2769 else {
2770 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2771 *pSize = pHddCtx->fw->size;
2772 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2773 __func__, *pSize);
2774 }
2775 }
2776 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2777
2778 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2779
2780 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2781 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2782 __func__, pfileName);
2783 retval = VOS_STATUS_E_FAILURE;
2784 }
2785
2786 else {
2787 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2788 *pSize = pHddCtx->nv->size;
2789 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2790 __func__, *pSize);
2791 }
2792 }
2793
2794 EXIT();
2795 return retval;
2796}
2797/**---------------------------------------------------------------------------
2798 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2799
2800 This is the function invoked by SME to inform the result of a full power
2801 request issued by HDD
2802
2803 \param - callbackcontext - Pointer to cookie
2804 status - result of request
2805
2806 \return - None
2807
2808--------------------------------------------------------------------------*/
2809void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2810{
2811 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2812
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002813 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002814 if(&pHddCtx->full_pwr_comp_var)
2815 {
2816 complete(&pHddCtx->full_pwr_comp_var);
2817 }
2818}
2819
2820/**---------------------------------------------------------------------------
2821
2822 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2823
2824 This is the function invoked by SME to inform the result of BMPS
2825 request issued by HDD
2826
2827 \param - callbackcontext - Pointer to cookie
2828 status - result of request
2829
2830 \return - None
2831
2832--------------------------------------------------------------------------*/
2833void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2834{
2835
2836 struct completion *completion_var = (struct completion*) callbackContext;
2837
2838 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2839 if(completion_var != NULL)
2840 {
2841 complete(completion_var);
2842 }
2843}
2844
2845/**---------------------------------------------------------------------------
2846
2847 \brief hdd_get_cfg_file_size() -
2848
2849 This function reads the configuration file using the request firmware
2850 API and returns the configuration file size.
2851
2852 \param - pCtx - Pointer to the adapter .
2853 - pFileName - Pointer to the file name.
2854 - pBufSize - Pointer to the buffer size.
2855
2856 \return - 0 for success, non zero for failure
2857
2858 --------------------------------------------------------------------------*/
2859
2860VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2861{
2862 int status;
2863 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2864
2865 ENTER();
2866
2867 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2868
2869 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2870 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2871 status = VOS_STATUS_E_FAILURE;
2872 }
2873 else {
2874 *pBufSize = pHddCtx->fw->size;
2875 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2876 release_firmware(pHddCtx->fw);
2877 pHddCtx->fw = NULL;
2878 }
2879
2880 EXIT();
2881 return VOS_STATUS_SUCCESS;
2882}
2883
2884/**---------------------------------------------------------------------------
2885
2886 \brief hdd_read_cfg_file() -
2887
2888 This function reads the configuration file using the request firmware
2889 API and returns the cfg data and the buffer size of the configuration file.
2890
2891 \param - pCtx - Pointer to the adapter .
2892 - pFileName - Pointer to the file name.
2893 - pBuffer - Pointer to the data buffer.
2894 - pBufSize - Pointer to the buffer size.
2895
2896 \return - 0 for success, non zero for failure
2897
2898 --------------------------------------------------------------------------*/
2899
2900VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2901 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2902{
2903 int status;
2904 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2905
2906 ENTER();
2907
2908 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2909
2910 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2911 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2912 return VOS_STATUS_E_FAILURE;
2913 }
2914 else {
2915 if(*pBufSize != pHddCtx->fw->size) {
2916 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2917 "file size", __func__);
2918 release_firmware(pHddCtx->fw);
2919 pHddCtx->fw = NULL;
2920 return VOS_STATUS_E_FAILURE;
2921 }
2922 else {
2923 if(pBuffer) {
2924 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2925 }
2926 release_firmware(pHddCtx->fw);
2927 pHddCtx->fw = NULL;
2928 }
2929 }
2930
2931 EXIT();
2932
2933 return VOS_STATUS_SUCCESS;
2934}
2935
2936/**---------------------------------------------------------------------------
2937
Jeff Johnson295189b2012-06-20 16:38:30 -07002938 \brief hdd_set_mac_address() -
2939
2940 This function sets the user specified mac address using
2941 the command ifconfig wlanX hw ether <mac adress>.
2942
2943 \param - dev - Pointer to the net device.
2944 - addr - Pointer to the sockaddr.
2945 \return - 0 for success, non zero for failure
2946
2947 --------------------------------------------------------------------------*/
2948
2949static int hdd_set_mac_address(struct net_device *dev, void *addr)
2950{
2951 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2952 struct sockaddr *psta_mac_addr = addr;
2953 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2954
2955 ENTER();
2956
2957 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2958
2959#ifdef HDD_SESSIONIZE
2960 // set the MAC address though the STA ID CFG.
2961 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2962 (v_U8_t *)&pAdapter->macAddressCurrent,
2963 sizeof( pAdapter->macAddressCurrent ),
2964 hdd_set_mac_addr_cb, VOS_FALSE );
2965#endif
2966
2967 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2968
2969 EXIT();
2970 return halStatus;
2971}
2972
2973tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2974{
2975 int i;
2976 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2977 {
2978 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2979 break;
2980 }
2981
2982 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2983 return NULL;
2984
2985 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2986 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2987}
2988
2989void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
2990{
2991 int i;
2992 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2993 {
2994 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
2995 {
2996 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
2997 break;
2998 }
2999 }
3000 return;
3001}
3002
3003#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3004 static struct net_device_ops wlan_drv_ops = {
3005 .ndo_open = hdd_open,
3006 .ndo_stop = hdd_stop,
3007 .ndo_uninit = hdd_uninit,
3008 .ndo_start_xmit = hdd_hard_start_xmit,
3009 .ndo_tx_timeout = hdd_tx_timeout,
3010 .ndo_get_stats = hdd_stats,
3011 .ndo_do_ioctl = hdd_ioctl,
3012 .ndo_set_mac_address = hdd_set_mac_address,
3013 .ndo_select_queue = hdd_select_queue,
3014#ifdef WLAN_FEATURE_PACKET_FILTERING
3015#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
3016 .ndo_set_rx_mode = hdd_set_multicast_list,
3017#else
3018 .ndo_set_multicast_list = hdd_set_multicast_list,
3019#endif //LINUX_VERSION_CODE
3020#endif
3021 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003022 static struct net_device_ops wlan_mon_drv_ops = {
3023 .ndo_open = hdd_mon_open,
3024 .ndo_stop = hdd_stop,
3025 .ndo_uninit = hdd_uninit,
3026 .ndo_start_xmit = hdd_mon_hard_start_xmit,
3027 .ndo_tx_timeout = hdd_tx_timeout,
3028 .ndo_get_stats = hdd_stats,
3029 .ndo_do_ioctl = hdd_ioctl,
3030 .ndo_set_mac_address = hdd_set_mac_address,
3031 };
Jeff Johnson295189b2012-06-20 16:38:30 -07003032
3033#endif
3034
3035void hdd_set_station_ops( struct net_device *pWlanDev )
3036{
3037#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3038 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
3039 pWlanDev->netdev_ops = &wlan_drv_ops;
3040#else
3041 pWlanDev->open = hdd_open;
3042 pWlanDev->stop = hdd_stop;
3043 pWlanDev->uninit = hdd_uninit;
3044 pWlanDev->hard_start_xmit = NULL;
3045 pWlanDev->tx_timeout = hdd_tx_timeout;
3046 pWlanDev->get_stats = hdd_stats;
3047 pWlanDev->do_ioctl = hdd_ioctl;
3048 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
3049 pWlanDev->set_mac_address = hdd_set_mac_address;
3050#endif
3051}
3052
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003053static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07003054{
3055 struct net_device *pWlanDev = NULL;
3056 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003057 /*
3058 * cfg80211 initialization and registration....
3059 */
3060 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
3061
Jeff Johnson295189b2012-06-20 16:38:30 -07003062 if(pWlanDev != NULL)
3063 {
3064
3065 //Save the pointer to the net_device in the HDD adapter
3066 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
3067
Jeff Johnson295189b2012-06-20 16:38:30 -07003068 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
3069
3070 pAdapter->dev = pWlanDev;
3071 pAdapter->pHddCtx = pHddCtx;
3072 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
3073
3074 init_completion(&pAdapter->session_open_comp_var);
3075 init_completion(&pAdapter->session_close_comp_var);
3076 init_completion(&pAdapter->disconnect_comp_var);
3077 init_completion(&pAdapter->linkup_event_var);
3078 init_completion(&pAdapter->cancel_rem_on_chan_var);
3079 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07003080#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
3081 init_completion(&pAdapter->offchannel_tx_event);
3082#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003083 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003084#ifdef FEATURE_WLAN_TDLS
3085 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07003086 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08003087 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05303088 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08003089#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003090 init_completion(&pHddCtx->mc_sus_event_var);
3091 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05303092 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07003093 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07003094
Jeff Johnson295189b2012-06-20 16:38:30 -07003095 pAdapter->isLinkUpSvcNeeded = FALSE;
3096 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
3097 //Init the net_device structure
3098 strlcpy(pWlanDev->name, name, IFNAMSIZ);
3099
3100 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
3101 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
3102 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
3103 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
3104
3105 hdd_set_station_ops( pAdapter->dev );
3106
3107 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003108 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
3109 pAdapter->wdev.wiphy = pHddCtx->wiphy;
3110 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07003111 /* set pWlanDev's parent to underlying device */
3112 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
3113 }
3114
3115 return pAdapter;
3116}
3117
3118VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
3119{
3120 struct net_device *pWlanDev = pAdapter->dev;
3121 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3122 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3123 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3124
3125 if( rtnl_lock_held )
3126 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08003127 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07003128 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
3129 {
3130 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
3131 return VOS_STATUS_E_FAILURE;
3132 }
3133 }
3134 if (register_netdevice(pWlanDev))
3135 {
3136 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
3137 return VOS_STATUS_E_FAILURE;
3138 }
3139 }
3140 else
3141 {
3142 if(register_netdev(pWlanDev))
3143 {
3144 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
3145 return VOS_STATUS_E_FAILURE;
3146 }
3147 }
3148 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
3149
3150 return VOS_STATUS_SUCCESS;
3151}
3152
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003153static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07003154{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003155 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07003156
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003157 if (NULL == pAdapter)
3158 {
3159 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
3160 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07003161 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003162
3163 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3164 {
3165 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
3166 return eHAL_STATUS_NOT_INITIALIZED;
3167 }
3168
3169 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
3170
3171 /* need to make sure all of our scheduled work has completed.
3172 * This callback is called from MC thread context, so it is safe to
3173 * to call below flush workqueue API from here.
3174 */
3175 flush_scheduled_work();
3176
3177 /* We can be blocked while waiting for scheduled work to be
3178 * flushed, and the adapter structure can potentially be freed, in
3179 * which case the magic will have been reset. So make sure the
3180 * magic is still good, and hence the adapter structure is still
3181 * valid, before signaling completion */
3182 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
3183 {
3184 complete(&pAdapter->session_close_comp_var);
3185 }
3186
Jeff Johnson295189b2012-06-20 16:38:30 -07003187 return eHAL_STATUS_SUCCESS;
3188}
3189
3190VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
3191{
3192 struct net_device *pWlanDev = pAdapter->dev;
3193 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
3194 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
3195 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3196 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3197 int rc = 0;
3198
3199 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003200 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07003201 //Open a SME session for future operation
3202 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07003203 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07003204 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3205 {
3206 hddLog(VOS_TRACE_LEVEL_FATAL,
3207 "sme_OpenSession() failed with status code %08d [x%08lx]",
3208 halStatus, halStatus );
3209 status = VOS_STATUS_E_FAILURE;
3210 goto error_sme_open;
3211 }
3212
3213 //Block on a completion variable. Can't wait forever though.
3214 rc = wait_for_completion_interruptible_timeout(
3215 &pAdapter->session_open_comp_var,
3216 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3217 if (!rc)
3218 {
3219 hddLog(VOS_TRACE_LEVEL_FATAL,
3220 "Session is not opened within timeout period code %08d", rc );
3221 status = VOS_STATUS_E_FAILURE;
3222 goto error_sme_open;
3223 }
3224
3225 // Register wireless extensions
3226 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
3227 {
3228 hddLog(VOS_TRACE_LEVEL_FATAL,
3229 "hdd_register_wext() failed with status code %08d [x%08lx]",
3230 halStatus, halStatus );
3231 status = VOS_STATUS_E_FAILURE;
3232 goto error_register_wext;
3233 }
3234 //Safe to register the hard_start_xmit function again
3235#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
3236 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
3237#else
3238 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
3239#endif
3240
3241 //Set the Connection State to Not Connected
3242 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3243
3244 //Set the default operation channel
3245 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
3246
3247 /* Make the default Auth Type as OPEN*/
3248 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3249
3250 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
3251 {
3252 hddLog(VOS_TRACE_LEVEL_FATAL,
3253 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
3254 status, status );
3255 goto error_init_txrx;
3256 }
3257
3258 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3259
3260 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
3261 {
3262 hddLog(VOS_TRACE_LEVEL_FATAL,
3263 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
3264 status, status );
3265 goto error_wmm_init;
3266 }
3267
3268 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3269
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003270#ifdef FEATURE_WLAN_TDLS
3271 if(0 != wlan_hdd_tdls_init(pAdapter))
3272 {
3273 status = VOS_STATUS_E_FAILURE;
3274 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
3275 goto error_tdls_init;
3276 }
3277 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3278#endif
3279
Jeff Johnson295189b2012-06-20 16:38:30 -07003280 return VOS_STATUS_SUCCESS;
3281
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003282#ifdef FEATURE_WLAN_TDLS
3283error_tdls_init:
3284 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3285 hdd_wmm_adapter_close(pAdapter);
3286#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003287error_wmm_init:
3288 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3289 hdd_deinit_tx_rx(pAdapter);
3290error_init_txrx:
3291 hdd_UnregisterWext(pWlanDev);
3292error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003293 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003294 {
3295 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003296 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003297 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003298 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003299 {
3300 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003301 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003302 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003303 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003304 }
3305}
3306error_sme_open:
3307 return status;
3308}
3309
Jeff Johnson295189b2012-06-20 16:38:30 -07003310void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3311{
3312 hdd_cfg80211_state_t *cfgState;
3313
3314 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3315
3316 if( NULL != cfgState->buf )
3317 {
3318 int rc;
3319 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3320 rc = wait_for_completion_interruptible_timeout(
3321 &pAdapter->tx_action_cnf_event,
3322 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3323 if(!rc)
3324 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003325 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003326 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3327 }
3328 }
3329 return;
3330}
Jeff Johnson295189b2012-06-20 16:38:30 -07003331
3332void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3333{
3334 ENTER();
3335 switch ( pAdapter->device_mode )
3336 {
3337 case WLAN_HDD_INFRA_STATION:
3338 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003339 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003340 {
3341 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3342 {
3343 hdd_deinit_tx_rx( pAdapter );
3344 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3345 }
3346
3347 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3348 {
3349 hdd_wmm_adapter_close( pAdapter );
3350 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3351 }
3352
Jeff Johnson295189b2012-06-20 16:38:30 -07003353 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003354#ifdef FEATURE_WLAN_TDLS
3355 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3356 {
3357 wlan_hdd_tdls_exit(pAdapter);
3358 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3359 }
3360#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003361
3362 break;
3363 }
3364
3365 case WLAN_HDD_SOFTAP:
3366 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003367 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003368 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003369
3370 hdd_unregister_hostapd(pAdapter);
3371 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003372 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003373 break;
3374 }
3375
3376 case WLAN_HDD_MONITOR:
3377 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003378 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003379 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3380 {
3381 hdd_deinit_tx_rx( pAdapter );
3382 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3383 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003384 if(NULL != pAdapterforTx)
3385 {
3386 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3387 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003388 break;
3389 }
3390
3391
3392 default:
3393 break;
3394 }
3395
3396 EXIT();
3397}
3398
3399void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3400{
3401 struct net_device *pWlanDev = pAdapter->dev;
3402
3403 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3404 if( rtnl_held )
3405 {
3406 unregister_netdevice(pWlanDev);
3407 }
3408 else
3409 {
3410 unregister_netdev(pWlanDev);
3411 }
3412 // note that the pAdapter is no longer valid at this point
3413 // since the memory has been reclaimed
3414 }
3415
3416}
3417
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003418void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3419{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303420 VOS_STATUS status;
3421 hdd_adapter_t *pAdapter = NULL;
3422 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003423
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303424 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003425
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303426 /*loop through all adapters.*/
3427 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003428 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303429 pAdapter = pAdapterNode->pAdapter;
3430 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
3431 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003432
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303433 { // we skip this registration for modes other than STA and P2P client modes.
3434 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3435 pAdapterNode = pNext;
3436 continue;
3437 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003438
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303439 //Apply Dynamic DTIM For P2P
3440 //Only if ignoreDynamicDtimInP2pMode is not set in ini
3441 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
3442 pHddCtx->cfg_ini->enableModulatedDTIM) &&
3443 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3444 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
3445 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
3446 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
3447 (eConnectionState_Associated ==
3448 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
3449 (pHddCtx->cfg_ini->fIsBmpsEnabled))
3450 {
3451 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003452
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303453 powerRequest.uIgnoreDTIM = 1;
3454 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
3455
3456 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3457 {
3458 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3459 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3460 }
3461 else
3462 {
3463 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3464 }
3465
3466 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3467 * specified during Enter/Exit BMPS when LCD off*/
3468 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3469 NULL, eANI_BOOLEAN_FALSE);
3470 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3471 NULL, eANI_BOOLEAN_FALSE);
3472
3473 /* switch to the DTIM specified in cfg.ini */
3474 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3475 "Switch to DTIM %d", powerRequest.uListenInterval);
3476 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3477 break;
3478
3479 }
3480
3481 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3482 pAdapterNode = pNext;
3483 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003484}
3485
3486void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3487{
3488 /*Switch back to DTIM 1*/
3489 tSirSetPowerParamsReq powerRequest = { 0 };
3490
3491 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3492 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003493 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003494
3495 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3496 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3497 NULL, eANI_BOOLEAN_FALSE);
3498 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3499 NULL, eANI_BOOLEAN_FALSE);
3500
3501 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3502 "Switch to DTIM%d",powerRequest.uListenInterval);
3503 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3504
3505}
3506
Jeff Johnson295189b2012-06-20 16:38:30 -07003507VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3508{
3509 VOS_STATUS status = VOS_STATUS_SUCCESS;
3510
3511 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3512 {
3513 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3514 }
3515
3516 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3517 {
3518 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3519 }
3520
3521 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3522 {
3523 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3524 }
3525
3526 return status;
3527}
3528
3529VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3530{
3531 hdd_adapter_t *pAdapter = NULL;
3532 eHalStatus halStatus;
3533 VOS_STATUS status = VOS_STATUS_E_INVAL;
3534 v_BOOL_t disableBmps = FALSE;
3535 v_BOOL_t disableImps = FALSE;
3536
3537 switch(session_type)
3538 {
3539 case WLAN_HDD_INFRA_STATION:
3540 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003541 case WLAN_HDD_P2P_CLIENT:
3542 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003543 //Exit BMPS -> Is Sta/P2P Client is already connected
3544 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3545 if((NULL != pAdapter)&&
3546 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3547 {
3548 disableBmps = TRUE;
3549 }
3550
3551 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3552 if((NULL != pAdapter)&&
3553 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3554 {
3555 disableBmps = TRUE;
3556 }
3557
3558 //Exit both Bmps and Imps incase of Go/SAP Mode
3559 if((WLAN_HDD_SOFTAP == session_type) ||
3560 (WLAN_HDD_P2P_GO == session_type))
3561 {
3562 disableBmps = TRUE;
3563 disableImps = TRUE;
3564 }
3565
3566 if(TRUE == disableImps)
3567 {
3568 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3569 {
3570 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3571 }
3572 }
3573
3574 if(TRUE == disableBmps)
3575 {
3576 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3577 {
3578 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3579
3580 if(eHAL_STATUS_SUCCESS != halStatus)
3581 {
3582 status = VOS_STATUS_E_FAILURE;
3583 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3584 VOS_ASSERT(0);
3585 return status;
3586 }
3587 }
3588
3589 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3590 {
3591 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3592
3593 if(eHAL_STATUS_SUCCESS != halStatus)
3594 {
3595 status = VOS_STATUS_E_FAILURE;
3596 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3597 VOS_ASSERT(0);
3598 return status;
3599 }
3600 }
3601 }
3602
3603 if((TRUE == disableBmps) ||
3604 (TRUE == disableImps))
3605 {
3606 /* Now, get the chip into Full Power now */
3607 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3608 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3609 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3610
3611 if(halStatus != eHAL_STATUS_SUCCESS)
3612 {
3613 if(halStatus == eHAL_STATUS_PMC_PENDING)
3614 {
3615 //Block on a completion variable. Can't wait forever though
3616 wait_for_completion_interruptible_timeout(
3617 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3618 }
3619 else
3620 {
3621 status = VOS_STATUS_E_FAILURE;
3622 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3623 VOS_ASSERT(0);
3624 return status;
3625 }
3626 }
3627
3628 status = VOS_STATUS_SUCCESS;
3629 }
3630
3631 break;
3632 }
3633 return status;
3634}
3635
3636hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003637 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003638 tANI_U8 rtnl_held )
3639{
3640 hdd_adapter_t *pAdapter = NULL;
3641 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3642 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3643 VOS_STATUS exitbmpsStatus;
3644
3645 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3646
3647 //Disable BMPS incase of Concurrency
3648 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3649
3650 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3651 {
3652 //Fail to Exit BMPS
3653 VOS_ASSERT(0);
3654 return NULL;
3655 }
3656
3657 switch(session_type)
3658 {
3659 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003660 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003661 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003662 {
3663 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3664
3665 if( NULL == pAdapter )
3666 return NULL;
3667
Jeff Johnsone7245742012-09-05 17:12:55 -07003668 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3669 NL80211_IFTYPE_P2P_CLIENT:
3670 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003671
Jeff Johnson295189b2012-06-20 16:38:30 -07003672 pAdapter->device_mode = session_type;
3673
3674 status = hdd_init_station_mode( pAdapter );
3675 if( VOS_STATUS_SUCCESS != status )
3676 goto err_free_netdev;
3677
3678 status = hdd_register_interface( pAdapter, rtnl_held );
3679 if( VOS_STATUS_SUCCESS != status )
3680 {
3681 hdd_deinit_adapter(pHddCtx, pAdapter);
3682 goto err_free_netdev;
3683 }
3684 //Stop the Interface TX queue.
3685 netif_tx_disable(pAdapter->dev);
3686 //netif_tx_disable(pWlanDev);
3687 netif_carrier_off(pAdapter->dev);
3688
3689 break;
3690 }
3691
Jeff Johnson295189b2012-06-20 16:38:30 -07003692 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003693 case WLAN_HDD_SOFTAP:
3694 {
3695 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3696 if( NULL == pAdapter )
3697 return NULL;
3698
Jeff Johnson295189b2012-06-20 16:38:30 -07003699 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3700 NL80211_IFTYPE_AP:
3701 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003702 pAdapter->device_mode = session_type;
3703
3704 status = hdd_init_ap_mode(pAdapter);
3705 if( VOS_STATUS_SUCCESS != status )
3706 goto err_free_netdev;
3707
3708 status = hdd_register_hostapd( pAdapter, rtnl_held );
3709 if( VOS_STATUS_SUCCESS != status )
3710 {
3711 hdd_deinit_adapter(pHddCtx, pAdapter);
3712 goto err_free_netdev;
3713 }
3714
3715 netif_tx_disable(pAdapter->dev);
3716 netif_carrier_off(pAdapter->dev);
3717
3718 hdd_set_conparam( 1 );
3719 break;
3720 }
3721 case WLAN_HDD_MONITOR:
3722 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003723 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3724 if( NULL == pAdapter )
3725 return NULL;
3726
3727 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3728 pAdapter->device_mode = session_type;
3729 status = hdd_register_interface( pAdapter, rtnl_held );
3730#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3731 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3732#else
3733 pAdapter->dev->open = hdd_mon_open;
3734 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3735#endif
3736 hdd_init_tx_rx( pAdapter );
3737 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3738 //Set adapter to be used for data tx. It will use either GO or softap.
3739 pAdapter->sessionCtx.monitor.pAdapterForTx =
3740 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003741 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3742 {
3743 pAdapter->sessionCtx.monitor.pAdapterForTx =
3744 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3745 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003746 /* This workqueue will be used to transmit management packet over
3747 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003748 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3749 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3750 return NULL;
3751 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003752
Jeff Johnson295189b2012-06-20 16:38:30 -07003753 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3754 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003755 }
3756 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003757 case WLAN_HDD_FTM:
3758 {
3759 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3760
3761 if( NULL == pAdapter )
3762 return NULL;
3763 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3764 * message while loading driver in FTM mode. */
3765 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3766 pAdapter->device_mode = session_type;
3767 status = hdd_register_interface( pAdapter, rtnl_held );
3768 }
3769 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003770 default:
3771 {
3772 VOS_ASSERT(0);
3773 return NULL;
3774 }
3775 }
3776
3777
3778 if( VOS_STATUS_SUCCESS == status )
3779 {
3780 //Add it to the hdd's session list.
3781 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3782 if( NULL == pHddAdapterNode )
3783 {
3784 status = VOS_STATUS_E_NOMEM;
3785 }
3786 else
3787 {
3788 pHddAdapterNode->pAdapter = pAdapter;
3789 status = hdd_add_adapter_back ( pHddCtx,
3790 pHddAdapterNode );
3791 }
3792 }
3793
3794 if( VOS_STATUS_SUCCESS != status )
3795 {
3796 if( NULL != pAdapter )
3797 {
3798 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3799 pAdapter = NULL;
3800 }
3801 if( NULL != pHddAdapterNode )
3802 {
3803 vos_mem_free( pHddAdapterNode );
3804 }
3805
3806 goto resume_bmps;
3807 }
3808
3809 if(VOS_STATUS_SUCCESS == status)
3810 {
3811 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3812
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003813 //Initialize the WoWL service
3814 if(!hdd_init_wowl(pAdapter))
3815 {
3816 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3817 goto err_free_netdev;
3818 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003819 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003820 return pAdapter;
3821
3822err_free_netdev:
3823 free_netdev(pAdapter->dev);
3824 wlan_hdd_release_intf_addr( pHddCtx,
3825 pAdapter->macAddressCurrent.bytes );
3826
3827resume_bmps:
3828 //If bmps disabled enable it
3829 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3830 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303831 if (pHddCtx->hdd_wlan_suspended)
3832 {
3833 hdd_set_pwrparams(pHddCtx);
3834 }
3835 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003836 }
3837 return NULL;
3838}
3839
3840VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3841 tANI_U8 rtnl_held )
3842{
3843 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3844 VOS_STATUS status;
3845
3846 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3847 if( VOS_STATUS_SUCCESS != status )
3848 return status;
3849
3850 while ( pCurrent->pAdapter != pAdapter )
3851 {
3852 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3853 if( VOS_STATUS_SUCCESS != status )
3854 break;
3855
3856 pCurrent = pNext;
3857 }
3858 pAdapterNode = pCurrent;
3859 if( VOS_STATUS_SUCCESS == status )
3860 {
3861 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3862 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3863 hdd_remove_adapter( pHddCtx, pAdapterNode );
3864 vos_mem_free( pAdapterNode );
3865
Jeff Johnson295189b2012-06-20 16:38:30 -07003866
3867 /* If there is a single session of STA/P2P client, re-enable BMPS */
3868 if ((!vos_concurrent_sessions_running()) &&
3869 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3870 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3871 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05303872 if (pHddCtx->hdd_wlan_suspended)
3873 {
3874 hdd_set_pwrparams(pHddCtx);
3875 }
3876 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003877 }
3878
3879 return VOS_STATUS_SUCCESS;
3880 }
3881
3882 return VOS_STATUS_E_FAILURE;
3883}
3884
3885VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3886{
3887 hdd_adapter_list_node_t *pHddAdapterNode;
3888 VOS_STATUS status;
3889
3890 ENTER();
3891
3892 do
3893 {
3894 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3895 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3896 {
3897 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3898 vos_mem_free( pHddAdapterNode );
3899 }
3900 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3901
3902 EXIT();
3903
3904 return VOS_STATUS_SUCCESS;
3905}
3906
3907void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3908{
3909 v_U8_t addIE[1] = {0};
3910
3911 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3912 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3913 eANI_BOOLEAN_FALSE) )
3914 {
3915 hddLog(LOGE,
3916 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3917 }
3918
3919 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3920 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3921 eANI_BOOLEAN_FALSE) )
3922 {
3923 hddLog(LOGE,
3924 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3925 }
3926
3927 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3928 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3929 eANI_BOOLEAN_FALSE) )
3930 {
3931 hddLog(LOGE,
3932 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3933 }
3934}
3935
3936VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3937{
3938 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3939 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3940 union iwreq_data wrqu;
3941
3942 ENTER();
3943
3944 switch(pAdapter->device_mode)
3945 {
3946 case WLAN_HDD_INFRA_STATION:
3947 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003948 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003949 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3950 {
3951 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3952 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3953 pAdapter->sessionId,
3954 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3955 else
3956 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3957 pAdapter->sessionId,
3958 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3959 //success implies disconnect command got queued up successfully
3960 if(halStatus == eHAL_STATUS_SUCCESS)
3961 {
3962 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3963 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3964 }
3965 memset(&wrqu, '\0', sizeof(wrqu));
3966 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3967 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3968 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3969 }
3970 else
3971 {
3972 hdd_abort_mac_scan(pHddCtx);
3973 }
3974
3975 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3976 {
3977 INIT_COMPLETION(pAdapter->session_close_comp_var);
3978 if (eHAL_STATUS_SUCCESS ==
3979 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3980 hdd_smeCloseSessionCallback, pAdapter))
3981 {
3982 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003983 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003984 &pAdapter->session_close_comp_var,
3985 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3986 }
3987 }
3988
3989 break;
3990
3991 case WLAN_HDD_SOFTAP:
3992 case WLAN_HDD_P2P_GO:
3993 //Any softap specific cleanup here...
3994 mutex_lock(&pHddCtx->sap_lock);
3995 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3996 {
3997 VOS_STATUS status;
3998 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3999
4000 //Stop Bss.
4001 status = WLANSAP_StopBss(pHddCtx->pvosContext);
4002 if (VOS_IS_STATUS_SUCCESS(status))
4003 {
4004 hdd_hostapd_state_t *pHostapdState =
4005 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4006
4007 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
4008
4009 if (!VOS_IS_STATUS_SUCCESS(status))
4010 {
4011 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004012 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004013 }
4014 }
4015 else
4016 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004017 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004018 }
4019 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
4020
4021 if (eHAL_STATUS_FAILURE ==
4022 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4023 0, NULL, eANI_BOOLEAN_FALSE))
4024 {
4025 hddLog(LOGE,
4026 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004027 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004028 }
4029
4030 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
4031 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
4032 eANI_BOOLEAN_FALSE) )
4033 {
4034 hddLog(LOGE,
4035 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
4036 }
4037
4038 // Reset WNI_CFG_PROBE_RSP Flags
4039 wlan_hdd_reset_prob_rspies(pAdapter);
4040 kfree(pAdapter->sessionCtx.ap.beacon);
4041 pAdapter->sessionCtx.ap.beacon = NULL;
4042 }
4043 mutex_unlock(&pHddCtx->sap_lock);
4044 break;
4045 case WLAN_HDD_MONITOR:
4046 break;
4047 default:
4048 break;
4049 }
4050
4051 EXIT();
4052 return VOS_STATUS_SUCCESS;
4053}
4054
4055VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
4056{
4057 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4058 VOS_STATUS status;
4059 hdd_adapter_t *pAdapter;
4060
4061 ENTER();
4062
4063 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4064
4065 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4066 {
4067 pAdapter = pAdapterNode->pAdapter;
4068 netif_tx_disable(pAdapter->dev);
4069 netif_carrier_off(pAdapter->dev);
4070
4071 hdd_stop_adapter( pHddCtx, pAdapter );
4072
4073 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4074 pAdapterNode = pNext;
4075 }
4076
4077 EXIT();
4078
4079 return VOS_STATUS_SUCCESS;
4080}
4081
4082VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
4083{
4084 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4085 VOS_STATUS status;
4086 hdd_adapter_t *pAdapter;
4087
4088 ENTER();
4089
4090 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4091
4092 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4093 {
4094 pAdapter = pAdapterNode->pAdapter;
4095 netif_tx_disable(pAdapter->dev);
4096 netif_carrier_off(pAdapter->dev);
4097
Jeff Johnson295189b2012-06-20 16:38:30 -07004098 hdd_deinit_tx_rx(pAdapter);
4099 hdd_wmm_adapter_close(pAdapter);
4100
4101 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4102 pAdapterNode = pNext;
4103 }
4104
4105 EXIT();
4106
4107 return VOS_STATUS_SUCCESS;
4108}
4109
4110VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
4111{
4112 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4113 VOS_STATUS status;
4114 hdd_adapter_t *pAdapter;
4115 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304116 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07004117
4118 ENTER();
4119
4120 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4121
4122 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4123 {
4124 pAdapter = pAdapterNode->pAdapter;
4125
4126 switch(pAdapter->device_mode)
4127 {
4128 case WLAN_HDD_INFRA_STATION:
4129 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004130 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304131
4132 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
4133
Jeff Johnson295189b2012-06-20 16:38:30 -07004134 hdd_init_station_mode(pAdapter);
4135 /* Open the gates for HDD to receive Wext commands */
4136 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004137 pHddCtx->scan_info.mScanPending = FALSE;
4138 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004139
4140 //Trigger the initial scan
4141 hdd_wlan_initial_scan(pAdapter);
4142
4143 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304144 if (eConnectionState_Associated == connState ||
4145 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07004146 {
4147 union iwreq_data wrqu;
4148 memset(&wrqu, '\0', sizeof(wrqu));
4149 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4150 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
4151 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004152
Jeff Johnson295189b2012-06-20 16:38:30 -07004153 /* indicate disconnected event to nl80211 */
4154 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
4155 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004156 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05304157 else if (eConnectionState_Connecting == connState)
4158 {
4159 /*
4160 * Indicate connect failure to supplicant if we were in the
4161 * process of connecting
4162 */
4163 cfg80211_connect_result(pAdapter->dev, NULL,
4164 NULL, 0, NULL, 0,
4165 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4166 GFP_KERNEL);
4167 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004168 break;
4169
4170 case WLAN_HDD_SOFTAP:
4171 /* softAP can handle SSR */
4172 break;
4173
4174 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004175 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
4176 __func__);
4177 /* event supplicant to restart */
4178 cfg80211_del_sta(pAdapter->dev,
4179 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004180 break;
4181
4182 case WLAN_HDD_MONITOR:
4183 /* monitor interface start */
4184 break;
4185 default:
4186 break;
4187 }
4188
4189 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4190 pAdapterNode = pNext;
4191 }
4192
4193 EXIT();
4194
4195 return VOS_STATUS_SUCCESS;
4196}
4197
4198VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
4199{
4200 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4201 hdd_adapter_t *pAdapter;
4202 VOS_STATUS status;
4203 v_U32_t roamId;
4204
4205 ENTER();
4206
4207 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4208
4209 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4210 {
4211 pAdapter = pAdapterNode->pAdapter;
4212
4213 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4214 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4215 {
4216 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4217 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
4218
4219 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4220 init_completion(&pAdapter->disconnect_comp_var);
4221 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
4222 eCSR_DISCONNECT_REASON_UNSPECIFIED);
4223
4224 wait_for_completion_interruptible_timeout(
4225 &pAdapter->disconnect_comp_var,
4226 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
4227
4228 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
4229 pHddCtx->isAmpAllowed = VOS_FALSE;
4230 sme_RoamConnect(pHddCtx->hHal,
4231 pAdapter->sessionId, &(pWextState->roamProfile),
4232 &roamId);
4233 }
4234
4235 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4236 pAdapterNode = pNext;
4237 }
4238
4239 EXIT();
4240
4241 return VOS_STATUS_SUCCESS;
4242}
4243
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07004244void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
4245{
4246 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4247 VOS_STATUS status;
4248 hdd_adapter_t *pAdapter;
4249 hdd_station_ctx_t *pHddStaCtx;
4250 hdd_ap_ctx_t *pHddApCtx;
4251 hdd_hostapd_state_t * pHostapdState;
4252 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
4253 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
4254 const char *p2pMode = "DEV";
4255 const char *ccMode = "Standalone";
4256 int n;
4257
4258 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4259 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4260 {
4261 pAdapter = pAdapterNode->pAdapter;
4262 switch (pAdapter->device_mode) {
4263 case WLAN_HDD_INFRA_STATION:
4264 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4265 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4266 staChannel = pHddStaCtx->conn_info.operationChannel;
4267 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
4268 }
4269 break;
4270 case WLAN_HDD_P2P_CLIENT:
4271 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4272 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
4273 p2pChannel = pHddStaCtx->conn_info.operationChannel;
4274 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
4275 p2pMode = "CLI";
4276 }
4277 break;
4278 case WLAN_HDD_P2P_GO:
4279 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4280 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4281 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4282 p2pChannel = pHddApCtx->operatingChannel;
4283 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
4284 }
4285 p2pMode = "GO";
4286 break;
4287 case WLAN_HDD_SOFTAP:
4288 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
4289 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
4290 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
4291 apChannel = pHddApCtx->operatingChannel;
4292 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
4293 }
4294 break;
4295 default:
4296 break;
4297 }
4298 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4299 pAdapterNode = pNext;
4300 }
4301 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
4302 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
4303 }
4304 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
4305 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
4306 if (p2pChannel > 0) {
4307 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
4308 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
4309 }
4310 if (apChannel > 0) {
4311 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
4312 apChannel, MAC_ADDR_ARRAY(apBssid));
4313 }
4314
4315 if (p2pChannel > 0 && apChannel > 0) {
4316 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
4317 }
4318}
4319
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004320bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004321{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004322 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07004323}
4324
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004325/* Once SSR is disabled then it cannot be set. */
4326void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07004327{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07004328 if (HDD_SSR_DISABLED == isSsrRequired)
4329 return;
4330
Jeff Johnson295189b2012-06-20 16:38:30 -07004331 isSsrRequired = value;
4332}
4333
4334VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
4335 hdd_adapter_list_node_t** ppAdapterNode)
4336{
4337 VOS_STATUS status;
4338 spin_lock(&pHddCtx->hddAdapters.lock);
4339 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4340 (hdd_list_node_t**) ppAdapterNode );
4341 spin_unlock(&pHddCtx->hddAdapters.lock);
4342 return status;
4343}
4344
4345VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4346 hdd_adapter_list_node_t* pAdapterNode,
4347 hdd_adapter_list_node_t** pNextAdapterNode)
4348{
4349 VOS_STATUS status;
4350 spin_lock(&pHddCtx->hddAdapters.lock);
4351 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4352 (hdd_list_node_t*) pAdapterNode,
4353 (hdd_list_node_t**)pNextAdapterNode );
4354
4355 spin_unlock(&pHddCtx->hddAdapters.lock);
4356 return status;
4357}
4358
4359VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4360 hdd_adapter_list_node_t* pAdapterNode)
4361{
4362 VOS_STATUS status;
4363 spin_lock(&pHddCtx->hddAdapters.lock);
4364 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4365 &pAdapterNode->node );
4366 spin_unlock(&pHddCtx->hddAdapters.lock);
4367 return status;
4368}
4369
4370VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4371 hdd_adapter_list_node_t** ppAdapterNode)
4372{
4373 VOS_STATUS status;
4374 spin_lock(&pHddCtx->hddAdapters.lock);
4375 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4376 (hdd_list_node_t**) ppAdapterNode );
4377 spin_unlock(&pHddCtx->hddAdapters.lock);
4378 return status;
4379}
4380
4381VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4382 hdd_adapter_list_node_t* pAdapterNode)
4383{
4384 VOS_STATUS status;
4385 spin_lock(&pHddCtx->hddAdapters.lock);
4386 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4387 (hdd_list_node_t*) pAdapterNode );
4388 spin_unlock(&pHddCtx->hddAdapters.lock);
4389 return status;
4390}
4391
4392VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4393 hdd_adapter_list_node_t* pAdapterNode)
4394{
4395 VOS_STATUS status;
4396 spin_lock(&pHddCtx->hddAdapters.lock);
4397 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4398 (hdd_list_node_t*) pAdapterNode );
4399 spin_unlock(&pHddCtx->hddAdapters.lock);
4400 return status;
4401}
4402
4403hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4404 tSirMacAddr macAddr )
4405{
4406 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4407 hdd_adapter_t *pAdapter;
4408 VOS_STATUS status;
4409
4410 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4411
4412 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4413 {
4414 pAdapter = pAdapterNode->pAdapter;
4415
4416 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4417 macAddr, sizeof(tSirMacAddr) ) )
4418 {
4419 return pAdapter;
4420 }
4421 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4422 pAdapterNode = pNext;
4423 }
4424
4425 return NULL;
4426
4427}
4428
4429hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4430{
4431 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4432 hdd_adapter_t *pAdapter;
4433 VOS_STATUS status;
4434
4435 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4436
4437 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4438 {
4439 pAdapter = pAdapterNode->pAdapter;
4440
4441 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4442 IFNAMSIZ ) )
4443 {
4444 return pAdapter;
4445 }
4446 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4447 pAdapterNode = pNext;
4448 }
4449
4450 return NULL;
4451
4452}
4453
4454hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4455{
4456 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4457 hdd_adapter_t *pAdapter;
4458 VOS_STATUS status;
4459
4460 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4461
4462 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4463 {
4464 pAdapter = pAdapterNode->pAdapter;
4465
4466 if( pAdapter && (mode == pAdapter->device_mode) )
4467 {
4468 return pAdapter;
4469 }
4470 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4471 pAdapterNode = pNext;
4472 }
4473
4474 return NULL;
4475
4476}
4477
4478//Remove this function later
4479hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4480{
4481 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4482 hdd_adapter_t *pAdapter;
4483 VOS_STATUS status;
4484
4485 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4486
4487 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4488 {
4489 pAdapter = pAdapterNode->pAdapter;
4490
4491 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4492 {
4493 return pAdapter;
4494 }
4495
4496 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4497 pAdapterNode = pNext;
4498 }
4499
4500 return NULL;
4501
4502}
4503
Jeff Johnson295189b2012-06-20 16:38:30 -07004504/**---------------------------------------------------------------------------
4505
4506 \brief hdd_set_monitor_tx_adapter() -
4507
4508 This API initializes the adapter to be used while transmitting on monitor
4509 adapter.
4510
4511 \param - pHddCtx - Pointer to the HDD context.
4512 pAdapter - Adapter that will used for TX. This can be NULL.
4513 \return - None.
4514 --------------------------------------------------------------------------*/
4515void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4516{
4517 hdd_adapter_t *pMonAdapter;
4518
4519 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4520
4521 if( NULL != pMonAdapter )
4522 {
4523 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4524 }
4525}
Jeff Johnson295189b2012-06-20 16:38:30 -07004526/**---------------------------------------------------------------------------
4527
4528 \brief hdd_select_queue() -
4529
4530 This API returns the operating channel of the requested device mode
4531
4532 \param - pHddCtx - Pointer to the HDD context.
4533 - mode - Device mode for which operating channel is required
4534 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4535 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4536 \return - channel number. "0" id the requested device is not found OR it is not connected.
4537 --------------------------------------------------------------------------*/
4538v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4539{
4540 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4541 VOS_STATUS status;
4542 hdd_adapter_t *pAdapter;
4543 v_U8_t operatingChannel = 0;
4544
4545 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4546
4547 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4548 {
4549 pAdapter = pAdapterNode->pAdapter;
4550
4551 if( mode == pAdapter->device_mode )
4552 {
4553 switch(pAdapter->device_mode)
4554 {
4555 case WLAN_HDD_INFRA_STATION:
4556 case WLAN_HDD_P2P_CLIENT:
4557 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4558 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4559 break;
4560 case WLAN_HDD_SOFTAP:
4561 case WLAN_HDD_P2P_GO:
4562 /*softap connection info */
4563 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4564 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4565 break;
4566 default:
4567 break;
4568 }
4569
4570 break; //Found the device of interest. break the loop
4571 }
4572
4573 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4574 pAdapterNode = pNext;
4575 }
4576 return operatingChannel;
4577}
4578
4579#ifdef WLAN_FEATURE_PACKET_FILTERING
4580/**---------------------------------------------------------------------------
4581
4582 \brief hdd_set_multicast_list() -
4583
4584 This used to set the multicast address list.
4585
4586 \param - dev - Pointer to the WLAN device.
4587 - skb - Pointer to OS packet (sk_buff).
4588 \return - success/fail
4589
4590 --------------------------------------------------------------------------*/
4591static void hdd_set_multicast_list(struct net_device *dev)
4592{
4593 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004594 int mc_count;
4595 int i = 0;
4596 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304597
4598 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004599 {
4600 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304601 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004602 return;
4603 }
4604
4605 if (dev->flags & IFF_ALLMULTI)
4606 {
4607 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004608 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304609 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004610 }
4611 else
4612 {
4613 mc_count = netdev_mc_count(dev);
4614 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004615 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004616 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4617 {
4618 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004619 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304620 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004621 return;
4622 }
4623
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304624 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004625
4626 netdev_for_each_mc_addr(ha, dev) {
4627 if (i == mc_count)
4628 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304629 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4630 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4631 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004632 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304633 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004634 i++;
4635 }
4636 }
4637 return;
4638}
4639#endif
4640
4641/**---------------------------------------------------------------------------
4642
4643 \brief hdd_select_queue() -
4644
4645 This function is registered with the Linux OS for network
4646 core to decide which queue to use first.
4647
4648 \param - dev - Pointer to the WLAN device.
4649 - skb - Pointer to OS packet (sk_buff).
4650 \return - ac, Queue Index/access category corresponding to UP in IP header
4651
4652 --------------------------------------------------------------------------*/
4653v_U16_t hdd_select_queue(struct net_device *dev,
4654 struct sk_buff *skb)
4655{
4656 return hdd_wmm_select_queue(dev, skb);
4657}
4658
4659
4660/**---------------------------------------------------------------------------
4661
4662 \brief hdd_wlan_initial_scan() -
4663
4664 This function triggers the initial scan
4665
4666 \param - pAdapter - Pointer to the HDD adapter.
4667
4668 --------------------------------------------------------------------------*/
4669void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4670{
4671 tCsrScanRequest scanReq;
4672 tCsrChannelInfo channelInfo;
4673 eHalStatus halStatus;
4674 unsigned long scanId;
4675 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4676
4677 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4678 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4679 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4680
4681 if(sme_Is11dSupported(pHddCtx->hHal))
4682 {
4683 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4684 if ( HAL_STATUS_SUCCESS( halStatus ) )
4685 {
4686 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4687 if( !scanReq.ChannelInfo.ChannelList )
4688 {
4689 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4690 vos_mem_free(channelInfo.ChannelList);
4691 return;
4692 }
4693 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4694 channelInfo.numOfChannels);
4695 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4696 vos_mem_free(channelInfo.ChannelList);
4697 }
4698
4699 scanReq.scanType = eSIR_PASSIVE_SCAN;
4700 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4701 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4702 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4703 }
4704 else
4705 {
4706 scanReq.scanType = eSIR_ACTIVE_SCAN;
4707 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4708 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4709 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4710 }
4711
4712 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4713 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4714 {
4715 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4716 __func__, halStatus );
4717 }
4718
4719 if(sme_Is11dSupported(pHddCtx->hHal))
4720 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4721}
4722
4723struct fullPowerContext
4724{
4725 struct completion completion;
4726 unsigned int magic;
4727};
4728#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4729
4730/**---------------------------------------------------------------------------
4731
4732 \brief hdd_full_power_callback() - HDD full power callback function
4733
4734 This is the function invoked by SME to inform the result of a full power
4735 request issued by HDD
4736
4737 \param - callbackcontext - Pointer to cookie
4738 \param - status - result of request
4739
4740 \return - None
4741
4742 --------------------------------------------------------------------------*/
4743static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4744{
4745 struct fullPowerContext *pContext = callbackContext;
4746
4747 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304748 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004749
4750 if (NULL == callbackContext)
4751 {
4752 hddLog(VOS_TRACE_LEVEL_ERROR,
4753 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004754 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004755 return;
4756 }
4757
4758 /* there is a race condition that exists between this callback function
4759 and the caller since the caller could time out either before or
4760 while this code is executing. we'll assume the timeout hasn't
4761 occurred, but we'll verify that right before we save our work */
4762
4763 if (POWER_CONTEXT_MAGIC != pContext->magic)
4764 {
4765 /* the caller presumably timed out so there is nothing we can do */
4766 hddLog(VOS_TRACE_LEVEL_WARN,
4767 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004768 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004769 return;
4770 }
4771
4772 /* the race is on. caller could have timed out immediately after
4773 we verified the magic, but if so, caller will wait a short time
4774 for us to notify the caller, so the context will stay valid */
4775 complete(&pContext->completion);
4776}
4777
4778/**---------------------------------------------------------------------------
4779
4780 \brief hdd_wlan_exit() - HDD WLAN exit function
4781
4782 This is the driver exit point (invoked during rmmod)
4783
4784 \param - pHddCtx - Pointer to the HDD Context
4785
4786 \return - None
4787
4788 --------------------------------------------------------------------------*/
4789void hdd_wlan_exit(hdd_context_t *pHddCtx)
4790{
4791 eHalStatus halStatus;
4792 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4793 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304794 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004795 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004796 struct fullPowerContext powerContext;
4797 long lrc;
4798
4799 ENTER();
4800
Jeff Johnson88ba7742013-02-27 14:36:02 -08004801 if (VOS_FTM_MODE != hdd_get_conparam())
4802 {
4803 // Unloading, restart logic is no more required.
4804 wlan_hdd_restart_deinit(pHddCtx);
4805 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004806
Jeff Johnson295189b2012-06-20 16:38:30 -07004807 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004808 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004809 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004810 {
4811 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4812 WLAN_HDD_INFRA_STATION);
4813 if (pAdapter == NULL)
4814 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4815
4816 if (pAdapter != NULL)
4817 {
4818 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4819 hdd_UnregisterWext(pAdapter->dev);
4820 }
4821 }
4822 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004823
Jeff Johnson295189b2012-06-20 16:38:30 -07004824 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004825 {
4826 wlan_hdd_ftm_close(pHddCtx);
4827 goto free_hdd_ctx;
4828 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004829 //Stop the Interface TX queue.
4830 //netif_tx_disable(pWlanDev);
4831 //netif_carrier_off(pWlanDev);
4832
Jeff Johnson295189b2012-06-20 16:38:30 -07004833 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4834 {
4835 pAdapter = hdd_get_adapter(pHddCtx,
4836 WLAN_HDD_SOFTAP);
4837 }
4838 else
4839 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004840 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004841 {
4842 pAdapter = hdd_get_adapter(pHddCtx,
4843 WLAN_HDD_INFRA_STATION);
4844 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004845 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004846 /* DeRegister with platform driver as client for Suspend/Resume */
4847 vosStatus = hddDeregisterPmOps(pHddCtx);
4848 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4849 {
4850 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4851 VOS_ASSERT(0);
4852 }
4853
4854 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4855 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4856 {
4857 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4858 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004859
4860 // Cancel any outstanding scan requests. We are about to close all
4861 // of our adapters, but an adapter structure is what SME passes back
4862 // to our callback function. Hence if there are any outstanding scan
4863 // requests then there is a race condition between when the adapter
4864 // is closed and when the callback is invoked. We try to resolve that
4865 // race condition here by canceling any outstanding scans before we
4866 // close the adapters.
4867 // Note that the scans may be cancelled in an asynchronous manner, so
4868 // ideally there needs to be some kind of synchronization. Rather than
4869 // introduce a new synchronization here, we will utilize the fact that
4870 // we are about to Request Full Power, and since that is synchronized,
4871 // the expectation is that by the time Request Full Power has completed,
4872 // all scans will be cancelled.
4873 hdd_abort_mac_scan( pHddCtx );
4874
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05304875 //Stop the timer if already running
4876 if (VOS_TIMER_STATE_RUNNING ==
4877 vos_timer_getCurrentState(&pHddCtx->hdd_p2p_go_conn_is_in_progress))
4878 {
4879 vos_timer_stop(&pHddCtx->hdd_p2p_go_conn_is_in_progress);
4880 }
4881
4882 // Destroy hdd_p2p_go_conn_is_in_progress timer
4883 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
4884 &pHddCtx->hdd_p2p_go_conn_is_in_progress)))
4885 {
4886 hddLog(VOS_TRACE_LEVEL_ERROR,
4887 "%s: Cannot deallocate p2p connection timer", __func__);
4888 }
4889
Jeff Johnson295189b2012-06-20 16:38:30 -07004890 //Disable IMPS/BMPS as we do not want the device to enter any power
4891 //save mode during shutdown
4892 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4893 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4894 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4895
4896 //Ensure that device is in full power as we will touch H/W during vos_Stop
4897 init_completion(&powerContext.completion);
4898 powerContext.magic = POWER_CONTEXT_MAGIC;
4899
4900 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4901 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4902
4903 if (eHAL_STATUS_SUCCESS != halStatus)
4904 {
4905 if (eHAL_STATUS_PMC_PENDING == halStatus)
4906 {
4907 /* request was sent -- wait for the response */
4908 lrc = wait_for_completion_interruptible_timeout(
4909 &powerContext.completion,
4910 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4911 /* either we have a response or we timed out
4912 either way, first invalidate our magic */
4913 powerContext.magic = 0;
4914 if (lrc <= 0)
4915 {
4916 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004917 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004918 /* there is a race condition such that the callback
4919 function could be executing at the same time we are. of
4920 primary concern is if the callback function had already
4921 verified the "magic" but hasn't yet set the completion
4922 variable. Since the completion variable is on our
4923 stack, we'll delay just a bit to make sure the data is
4924 still valid if that is the case */
4925 msleep(50);
4926 }
4927 }
4928 else
4929 {
4930 hddLog(VOS_TRACE_LEVEL_ERROR,
4931 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004932 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004933 VOS_ASSERT(0);
4934 /* continue -- need to clean up as much as possible */
4935 }
4936 }
4937
4938 // Unregister the Net Device Notifier
4939 unregister_netdevice_notifier(&hdd_netdev_notifier);
4940
Jeff Johnson295189b2012-06-20 16:38:30 -07004941 hdd_stop_all_adapters( pHddCtx );
4942
Jeff Johnson295189b2012-06-20 16:38:30 -07004943#ifdef WLAN_BTAMP_FEATURE
4944 vosStatus = WLANBAP_Stop(pVosContext);
4945 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4946 {
4947 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4948 "%s: Failed to stop BAP",__func__);
4949 }
4950#endif //WLAN_BTAMP_FEATURE
4951
4952 //Stop all the modules
4953 vosStatus = vos_stop( pVosContext );
4954 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4955 {
4956 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4957 "%s: Failed to stop VOSS",__func__);
4958 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4959 }
4960
Jeff Johnson295189b2012-06-20 16:38:30 -07004961 //Assert Deep sleep signal now to put Libra HW in lowest power state
4962 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4963 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4964
4965 //Vote off any PMIC voltage supplies
4966 vos_chipPowerDown(NULL, NULL, NULL);
4967
4968 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4969
Jeff Johnson295189b2012-06-20 16:38:30 -07004970 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004971 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004972
4973 //Close the scheduler before calling vos_close to make sure no thread is
4974 // scheduled after the each module close is called i.e after all the data
4975 // structures are freed.
4976 vosStatus = vos_sched_close( pVosContext );
4977 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4978 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4979 "%s: Failed to close VOSS Scheduler",__func__);
4980 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4981 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004982#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004983#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4984 /* Destroy the wake lock */
4985 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4986#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004987 /* Destroy the wake lock */
4988 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004989#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004990
4991 //Close VOSS
4992 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4993 vos_close(pVosContext);
4994
Jeff Johnson295189b2012-06-20 16:38:30 -07004995 //Close Watchdog
4996 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4997 vos_watchdog_close(pVosContext);
4998
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05304999 //Clean up HDD Nlink Service
5000 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
5001 nl_srv_exit();
5002
Jeff Johnson295189b2012-06-20 16:38:30 -07005003 /* Cancel the vote for XO Core ON.
5004 * This is done here to ensure there is no race condition since MC, TX and WD threads have
5005 * exited at this point
5006 */
5007 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
5008 " when WLAN is turned OFF\n");
5009 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5010 {
5011 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
5012 " Not returning failure."
5013 " Power consumed will be high\n");
5014 }
5015
5016 hdd_close_all_adapters( pHddCtx );
5017
5018
5019 //Free up dynamically allocated members inside HDD Adapter
5020 kfree(pHddCtx->cfg_ini);
5021 pHddCtx->cfg_ini= NULL;
5022
5023 /* free the power on lock from platform driver */
5024 if (free_riva_power_on_lock("wlan"))
5025 {
5026 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
5027 __func__);
5028 }
5029
Jeff Johnson88ba7742013-02-27 14:36:02 -08005030free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08005031 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005032 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005033 if (hdd_is_ssr_required())
5034 {
5035 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07005036 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07005037 msleep(5000);
5038 }
5039 hdd_set_ssr_required (VOS_FALSE);
5040}
5041
5042
5043/**---------------------------------------------------------------------------
5044
5045 \brief hdd_update_config_from_nv() - Function to update the contents of
5046 the running configuration with parameters taken from NV storage
5047
5048 \param - pHddCtx - Pointer to the HDD global context
5049
5050 \return - VOS_STATUS_SUCCESS if successful
5051
5052 --------------------------------------------------------------------------*/
5053static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
5054{
Jeff Johnson295189b2012-06-20 16:38:30 -07005055 v_BOOL_t itemIsValid = VOS_FALSE;
5056 VOS_STATUS status;
5057 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
5058 v_U8_t macLoop;
5059
5060 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
5061 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
5062 if(status != VOS_STATUS_SUCCESS)
5063 {
5064 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
5065 return VOS_STATUS_E_FAILURE;
5066 }
5067
5068 if (itemIsValid == VOS_TRUE)
5069 {
5070 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
5071 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
5072 VOS_MAX_CONCURRENCY_PERSONA);
5073 if(status != VOS_STATUS_SUCCESS)
5074 {
5075 /* Get MAC from NV fail, not update CFG info
5076 * INI MAC value will be used for MAC setting */
5077 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
5078 return VOS_STATUS_E_FAILURE;
5079 }
5080
5081 /* If first MAC is not valid, treat all others are not valid
5082 * Then all MACs will be got from ini file */
5083 if(vos_is_macaddr_zero(&macFromNV[0]))
5084 {
5085 /* MAC address in NV file is not configured yet */
5086 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
5087 return VOS_STATUS_E_INVAL;
5088 }
5089
5090 /* Get MAC address from NV, update CFG info */
5091 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
5092 {
5093 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
5094 {
5095 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
5096 /* This MAC is not valid, skip it
5097 * This MAC will be got from ini file */
5098 }
5099 else
5100 {
5101 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
5102 (v_U8_t *)&macFromNV[macLoop].bytes[0],
5103 VOS_MAC_ADDR_SIZE);
5104 }
5105 }
5106 }
5107 else
5108 {
5109 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
5110 return VOS_STATUS_E_FAILURE;
5111 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005112
Jeff Johnson295189b2012-06-20 16:38:30 -07005113
5114 return VOS_STATUS_SUCCESS;
5115}
5116
5117/**---------------------------------------------------------------------------
5118
5119 \brief hdd_post_voss_start_config() - HDD post voss start config helper
5120
5121 \param - pAdapter - Pointer to the HDD
5122
5123 \return - None
5124
5125 --------------------------------------------------------------------------*/
5126VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
5127{
5128 eHalStatus halStatus;
5129 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305130 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07005131
Jeff Johnson295189b2012-06-20 16:38:30 -07005132
5133 // Send ready indication to the HDD. This will kick off the MAC
5134 // into a 'running' state and should kick off an initial scan.
5135 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
5136 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5137 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305138 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07005139 "code %08d [x%08x]",__func__, halStatus, halStatus );
5140 return VOS_STATUS_E_FAILURE;
5141 }
5142
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305143 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07005144 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
5145 // And RIVA will crash
5146 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
5147 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305148 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
5149 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
5150
5151
Jeff Johnson295189b2012-06-20 16:38:30 -07005152 return VOS_STATUS_SUCCESS;
5153}
5154
Jeff Johnson295189b2012-06-20 16:38:30 -07005155/* wake lock APIs for HDD */
5156void hdd_prevent_suspend(void)
5157{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005158#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005159 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005160#else
5161 wcnss_prevent_suspend();
5162#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005163}
5164
5165void hdd_allow_suspend(void)
5166{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005167#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005168 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005169#else
5170 wcnss_allow_suspend();
5171#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005172}
5173
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005174void hdd_allow_suspend_timeout(v_U32_t timeout)
5175{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005176#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07005177 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07005178#else
5179 /* Do nothing as there is no API in wcnss for timeout*/
5180#endif
5181}
5182
Jeff Johnson295189b2012-06-20 16:38:30 -07005183/**---------------------------------------------------------------------------
5184
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005185 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
5186 information between Host and Riva
5187
5188 This function gets reported version of FW
5189 It also finds the version of Riva headers used to compile the host
5190 It compares the above two and prints a warning if they are different
5191 It gets the SW and HW version string
5192 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
5193 indicating the features they support through a bitmap
5194
5195 \param - pHddCtx - Pointer to HDD context
5196
5197 \return - void
5198
5199 --------------------------------------------------------------------------*/
5200
5201void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
5202{
5203
5204 tSirVersionType versionCompiled;
5205 tSirVersionType versionReported;
5206 tSirVersionString versionString;
5207 tANI_U8 fwFeatCapsMsgSupported = 0;
5208 VOS_STATUS vstatus;
5209
5210 /* retrieve and display WCNSS version information */
5211 do {
5212
5213 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
5214 &versionCompiled);
5215 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5216 {
5217 hddLog(VOS_TRACE_LEVEL_FATAL,
5218 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005219 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005220 break;
5221 }
5222
5223 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
5224 &versionReported);
5225 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5226 {
5227 hddLog(VOS_TRACE_LEVEL_FATAL,
5228 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005229 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005230 break;
5231 }
5232
5233 if ((versionCompiled.major != versionReported.major) ||
5234 (versionCompiled.minor != versionReported.minor) ||
5235 (versionCompiled.version != versionReported.version) ||
5236 (versionCompiled.revision != versionReported.revision))
5237 {
5238 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5239 "Host expected %u.%u.%u.%u\n",
5240 WLAN_MODULE_NAME,
5241 (int)versionReported.major,
5242 (int)versionReported.minor,
5243 (int)versionReported.version,
5244 (int)versionReported.revision,
5245 (int)versionCompiled.major,
5246 (int)versionCompiled.minor,
5247 (int)versionCompiled.version,
5248 (int)versionCompiled.revision);
5249 }
5250 else
5251 {
5252 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5253 WLAN_MODULE_NAME,
5254 (int)versionReported.major,
5255 (int)versionReported.minor,
5256 (int)versionReported.version,
5257 (int)versionReported.revision);
5258 }
5259
5260 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
5261 versionString,
5262 sizeof(versionString));
5263 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5264 {
5265 hddLog(VOS_TRACE_LEVEL_FATAL,
5266 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005267 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005268 break;
5269 }
5270
5271 pr_info("%s: WCNSS software version %s\n",
5272 WLAN_MODULE_NAME, versionString);
5273
5274 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
5275 versionString,
5276 sizeof(versionString));
5277 if (!VOS_IS_STATUS_SUCCESS(vstatus))
5278 {
5279 hddLog(VOS_TRACE_LEVEL_FATAL,
5280 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005281 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005282 break;
5283 }
5284
5285 pr_info("%s: WCNSS hardware version %s\n",
5286 WLAN_MODULE_NAME, versionString);
5287
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005288 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
5289 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005290 send the message only if it the riva is 1.1
5291 minor numbers for different riva branches:
5292 0 -> (1.0)Mainline Build
5293 1 -> (1.1)Mainline Build
5294 2->(1.04) Stability Build
5295 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005296 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005297 ((versionReported.minor>=1) && (versionReported.version>=1)))
5298 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
5299 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005300
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005301 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08005302 {
5303#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5304 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
5305 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
5306#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005307 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08005308 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005309
5310 } while (0);
5311
5312}
5313
5314/**---------------------------------------------------------------------------
5315
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305316 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
5317
5318 \param - pHddCtx - Pointer to the hdd context
5319
5320 \return - true if hardware supports 5GHz
5321
5322 --------------------------------------------------------------------------*/
5323static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
5324{
5325 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
5326 * then hardware support 5Ghz.
5327 */
5328 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
5329 {
5330 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
5331 return true;
5332 }
5333 else
5334 {
5335 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
5336 __func__);
5337 return false;
5338 }
5339}
5340
5341
5342/**---------------------------------------------------------------------------
5343
Jeff Johnson295189b2012-06-20 16:38:30 -07005344 \brief hdd_wlan_startup() - HDD init function
5345
5346 This is the driver startup code executed once a WLAN device has been detected
5347
5348 \param - dev - Pointer to the underlying device
5349
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005350 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07005351
5352 --------------------------------------------------------------------------*/
5353
5354int hdd_wlan_startup(struct device *dev )
5355{
5356 VOS_STATUS status;
5357 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07005358 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005359 hdd_context_t *pHddCtx = NULL;
5360 v_CONTEXT_t pVosContext= NULL;
5361#ifdef WLAN_BTAMP_FEATURE
5362 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
5363 WLANBAP_ConfigType btAmpConfig;
5364 hdd_config_t *pConfig;
5365#endif
5366 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005367 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005368
5369 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005370 /*
5371 * cfg80211: wiphy allocation
5372 */
5373 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
5374
5375 if(wiphy == NULL)
5376 {
5377 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005378 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005379 }
5380
5381 pHddCtx = wiphy_priv(wiphy);
5382
Jeff Johnson295189b2012-06-20 16:38:30 -07005383 //Initialize the adapter context to zeros.
5384 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
5385
Jeff Johnson295189b2012-06-20 16:38:30 -07005386 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005387 hdd_prevent_suspend();
5388 pHddCtx->isLoadUnloadInProgress = TRUE;
5389
5390 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5391
5392 /*Get vos context here bcoz vos_open requires it*/
5393 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5394
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005395 if(pVosContext == NULL)
5396 {
5397 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5398 goto err_free_hdd_context;
5399 }
5400
Jeff Johnson295189b2012-06-20 16:38:30 -07005401 //Save the Global VOSS context in adapter context for future.
5402 pHddCtx->pvosContext = pVosContext;
5403
5404 //Save the adapter context in global context for future.
5405 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5406
Jeff Johnson295189b2012-06-20 16:38:30 -07005407 pHddCtx->parent_dev = dev;
5408
5409 init_completion(&pHddCtx->full_pwr_comp_var);
5410 init_completion(&pHddCtx->standby_comp_var);
5411 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005412 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005413 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005414
5415 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5416
5417 // Load all config first as TL config is needed during vos_open
5418 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5419 if(pHddCtx->cfg_ini == NULL)
5420 {
5421 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5422 goto err_free_hdd_context;
5423 }
5424
5425 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5426
5427 // Read and parse the qcom_cfg.ini file
5428 status = hdd_parse_config_ini( pHddCtx );
5429 if ( VOS_STATUS_SUCCESS != status )
5430 {
5431 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5432 __func__, WLAN_INI_FILE);
5433 goto err_config;
5434 }
5435
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05305436 /* INI has been read, initialise the configuredMcastBcastFilter with
5437 * INI value as this will serve as the default value
5438 */
5439 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
5440 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
5441 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05305442
5443 if (false == hdd_is_5g_supported(pHddCtx))
5444 {
5445 //5Ghz is not supported.
5446 if (1 != pHddCtx->cfg_ini->nBandCapability)
5447 {
5448 hddLog(VOS_TRACE_LEVEL_INFO,
5449 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
5450 pHddCtx->cfg_ini->nBandCapability = 1;
5451 }
5452 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005453 /*
5454 * cfg80211: Initialization and registration ...
5455 */
5456 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
5457 {
5458 hddLog(VOS_TRACE_LEVEL_FATAL,
5459 "%s: wlan_hdd_cfg80211_register return failure", __func__);
5460 goto err_wiphy_reg;
5461 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005462
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005463 // Update VOS trace levels based upon the cfg.ini
5464 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5465 pHddCtx->cfg_ini->vosTraceEnableBAP);
5466 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5467 pHddCtx->cfg_ini->vosTraceEnableTL);
5468 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5469 pHddCtx->cfg_ini->vosTraceEnableWDI);
5470 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5471 pHddCtx->cfg_ini->vosTraceEnableHDD);
5472 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5473 pHddCtx->cfg_ini->vosTraceEnableSME);
5474 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5475 pHddCtx->cfg_ini->vosTraceEnablePE);
5476 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5477 pHddCtx->cfg_ini->vosTraceEnableWDA);
5478 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5479 pHddCtx->cfg_ini->vosTraceEnableSYS);
5480 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5481 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005482 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5483 pHddCtx->cfg_ini->vosTraceEnableSAP);
5484 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5485 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005486
Jeff Johnson295189b2012-06-20 16:38:30 -07005487 // Update WDI trace levels based upon the cfg.ini
5488 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5489 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5490 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5491 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5492 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5493 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5494 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5495 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005496
Jeff Johnson88ba7742013-02-27 14:36:02 -08005497 if (VOS_FTM_MODE == hdd_get_conparam())
5498 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005499 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5500 {
5501 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5502 goto err_free_hdd_context;
5503 }
5504 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5505 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005506 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005507
Jeff Johnson88ba7742013-02-27 14:36:02 -08005508 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005509 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5510 {
5511 status = vos_watchdog_open(pVosContext,
5512 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5513
5514 if(!VOS_IS_STATUS_SUCCESS( status ))
5515 {
5516 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005517 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005518 }
5519 }
5520
5521 pHddCtx->isLogpInProgress = FALSE;
5522 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5523
Jeff Johnson295189b2012-06-20 16:38:30 -07005524 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5525 if(!VOS_IS_STATUS_SUCCESS(status))
5526 {
5527 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005528 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005529 }
5530
Jeff Johnson295189b2012-06-20 16:38:30 -07005531 status = vos_open( &pVosContext, 0);
5532 if ( !VOS_IS_STATUS_SUCCESS( status ))
5533 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005534 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5535 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005536 }
5537
Jeff Johnson295189b2012-06-20 16:38:30 -07005538 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5539
5540 if ( NULL == pHddCtx->hHal )
5541 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005542 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005543 goto err_vosclose;
5544 }
5545
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005546 status = vos_preStart( pHddCtx->pvosContext );
5547 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5548 {
5549 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5550 goto err_vosclose;
5551 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005552
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005553 /* Note that the vos_preStart() sequence triggers the cfg download.
5554 The cfg download must occur before we update the SME config
5555 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005556 status = hdd_set_sme_config( pHddCtx );
5557
5558 if ( VOS_STATUS_SUCCESS != status )
5559 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005560 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5561 goto err_vosclose;
5562 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005563
5564 //Initialize the WMM module
5565 status = hdd_wmm_init(pHddCtx);
5566 if (!VOS_IS_STATUS_SUCCESS(status))
5567 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005568 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005569 goto err_vosclose;
5570 }
5571
Jeff Johnson295189b2012-06-20 16:38:30 -07005572 /* In the integrated architecture we update the configuration from
5573 the INI file and from NV before vOSS has been started so that
5574 the final contents are available to send down to the cCPU */
5575
5576 // Apply the cfg.ini to cfg.dat
5577 if (FALSE == hdd_update_config_dat(pHddCtx))
5578 {
5579 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5580 goto err_vosclose;
5581 }
5582
5583 // Apply the NV to cfg.dat
5584 /* Prima Update MAC address only at here */
5585 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5586 {
5587#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5588 /* There was not a valid set of MAC Addresses in NV. See if the
5589 default addresses were modified by the cfg.ini settings. If so,
5590 we'll use them, but if not, we'll autogenerate a set of MAC
5591 addresses based upon the device serial number */
5592
5593 static const v_MACADDR_t default_address =
5594 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5595 unsigned int serialno;
5596 int i;
5597
5598 serialno = wcnss_get_serial_number();
5599 if ((0 != serialno) &&
5600 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5601 sizeof(default_address))))
5602 {
5603 /* cfg.ini has the default address, invoke autogen logic */
5604
5605 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5606 bytes of the serial number that can be used to generate
5607 the other 3 bytes of the MAC address. Mask off all but
5608 the lower 3 bytes (this will also make sure we don't
5609 overflow in the next step) */
5610 serialno &= 0x00FFFFFF;
5611
5612 /* we need a unique address for each session */
5613 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5614
5615 /* autogen all addresses */
5616 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5617 {
5618 /* start with the entire default address */
5619 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5620 /* then replace the lower 3 bytes */
5621 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5622 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5623 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5624
5625 serialno++;
5626 }
5627
5628 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5629 MAC_ADDRESS_STR,
5630 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5631 }
5632 else
5633#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5634 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005635 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005636 "%s: Invalid MAC address in NV, using MAC from ini file "
5637 MAC_ADDRESS_STR, __func__,
5638 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5639 }
5640 }
5641 {
5642 eHalStatus halStatus;
5643 // Set the MAC Address
5644 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5645 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5646 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5647 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5648
5649 if (!HAL_STATUS_SUCCESS( halStatus ))
5650 {
5651 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5652 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005653 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005654 }
5655 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005656
5657 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5658 Note: Firmware image will be read and downloaded inside vos_start API */
5659 status = vos_start( pHddCtx->pvosContext );
5660 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5661 {
5662 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5663 goto err_vosclose;
5664 }
5665
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005666 /* Exchange capability info between Host and FW and also get versioning info from FW */
5667 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005668
5669 status = hdd_post_voss_start_config( pHddCtx );
5670 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5671 {
5672 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5673 __func__);
5674 goto err_vosstop;
5675 }
5676
Jeff Johnson295189b2012-06-20 16:38:30 -07005677 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5678 {
5679 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5680 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5681 }
5682 else
5683 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005684 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5685 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5686 if (pAdapter != NULL)
5687 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305688 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005689 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305690 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5691 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5692 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005693
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305694 /* Generate the P2P Device Address. This consists of the device's
5695 * primary MAC address with the locally administered bit set.
5696 */
5697 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005698 }
5699 else
5700 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305701 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5702 if (p2p_dev_addr != NULL)
5703 {
5704 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5705 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5706 }
5707 else
5708 {
5709 hddLog(VOS_TRACE_LEVEL_FATAL,
5710 "%s: Failed to allocate mac_address for p2p_device",
5711 __func__);
5712 goto err_close_adapter;
5713 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005714 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005715
5716 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5717 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5718 if ( NULL == pP2pAdapter )
5719 {
5720 hddLog(VOS_TRACE_LEVEL_FATAL,
5721 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005722 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005723 goto err_close_adapter;
5724 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005725 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005726 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005727
5728 if( pAdapter == NULL )
5729 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005730 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5731 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005732 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005733
Jeff Johnson295189b2012-06-20 16:38:30 -07005734#ifdef WLAN_BTAMP_FEATURE
5735 vStatus = WLANBAP_Open(pVosContext);
5736 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5737 {
5738 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5739 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005740 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005741 }
5742
5743 vStatus = BSL_Init(pVosContext);
5744 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5745 {
5746 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5747 "%s: Failed to Init BSL",__func__);
5748 goto err_bap_close;
5749 }
5750 vStatus = WLANBAP_Start(pVosContext);
5751 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5752 {
5753 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5754 "%s: Failed to start TL",__func__);
5755 goto err_bap_close;
5756 }
5757
5758 pConfig = pHddCtx->cfg_ini;
5759 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5760 status = WLANBAP_SetConfig(&btAmpConfig);
5761
5762#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005763
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005764#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5765 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5766 {
5767 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5768 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5769 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5770 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5771 }
5772#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005773#ifdef FEATURE_WLAN_SCAN_PNO
5774 /*SME must send channel update configuration to RIVA*/
5775 sme_UpdateChannelConfig(pHddCtx->hHal);
5776#endif
5777
Jeff Johnson295189b2012-06-20 16:38:30 -07005778 /* Register with platform driver as client for Suspend/Resume */
5779 status = hddRegisterPmOps(pHddCtx);
5780 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5781 {
5782 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5783#ifdef WLAN_BTAMP_FEATURE
5784 goto err_bap_stop;
5785#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005786 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005787#endif //WLAN_BTAMP_FEATURE
5788 }
5789
5790 /* Register TM level change handler function to the platform */
5791 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5792 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5793 {
5794 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5795 goto err_unregister_pmops;
5796 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005797
5798 /* register for riva power on lock to platform driver */
5799 if (req_riva_power_on_lock("wlan"))
5800 {
5801 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5802 __func__);
5803 goto err_unregister_pmops;
5804 }
5805
Jeff Johnson295189b2012-06-20 16:38:30 -07005806 // register net device notifier for device change notification
5807 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5808
5809 if(ret < 0)
5810 {
5811 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5812 goto err_free_power_on_lock;
5813 }
5814
5815 //Initialize the nlink service
5816 if(nl_srv_init() != 0)
5817 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305818 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005819 goto err_reg_netdev;
5820 }
5821
5822 //Initialize the BTC service
5823 if(btc_activate_service(pHddCtx) != 0)
5824 {
5825 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5826 goto err_nl_srv;
5827 }
5828
5829#ifdef PTT_SOCK_SVC_ENABLE
5830 //Initialize the PTT service
5831 if(ptt_sock_activate_svc(pHddCtx) != 0)
5832 {
5833 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5834 goto err_nl_srv;
5835 }
5836#endif
5837
Jeff Johnson295189b2012-06-20 16:38:30 -07005838 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005839 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005840 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005841 /* Action frame registered in one adapter which will
5842 * applicable to all interfaces
5843 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005844 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005845 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005846
5847 mutex_init(&pHddCtx->sap_lock);
5848
5849 pHddCtx->isLoadUnloadInProgress = FALSE;
5850
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005851#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005852#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5853 /* Initialize the wake lcok */
5854 wake_lock_init(&pHddCtx->rx_wake_lock,
5855 WAKE_LOCK_SUSPEND,
5856 "qcom_rx_wakelock");
5857#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005858 /* Initialize the wake lcok */
5859 wake_lock_init(&pHddCtx->sap_wake_lock,
5860 WAKE_LOCK_SUSPEND,
5861 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005862#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005863
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005864 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5865 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005866
5867 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5868 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05305869
Jeff Johnsone7245742012-09-05 17:12:55 -07005870 // Initialize the restart logic
5871 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305872
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05305873 if (!VOS_IS_STATUS_SUCCESS( vos_timer_init( &pHddCtx->hdd_p2p_go_conn_is_in_progress,
5874 VOS_TIMER_TYPE_SW, wlan_hdd_p2p_go_connection_in_progresscb, pAdapter) ) )
5875 {
5876 hddLog(VOS_TRACE_LEVEL_ERROR,
5877 "%s: vos timer init failed for hdd_p2p_go_conn_is_in_progress", __func__);
5878 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005879 goto success;
5880
5881err_nl_srv:
5882 nl_srv_exit();
5883
5884err_reg_netdev:
5885 unregister_netdevice_notifier(&hdd_netdev_notifier);
5886
5887err_free_power_on_lock:
5888 free_riva_power_on_lock("wlan");
5889
5890err_unregister_pmops:
5891 hddDevTmUnregisterNotifyCallback(pHddCtx);
5892 hddDeregisterPmOps(pHddCtx);
5893
5894#ifdef WLAN_BTAMP_FEATURE
5895err_bap_stop:
5896 WLANBAP_Stop(pVosContext);
5897#endif
5898
5899#ifdef WLAN_BTAMP_FEATURE
5900err_bap_close:
5901 WLANBAP_Close(pVosContext);
5902#endif
5903
Jeff Johnson295189b2012-06-20 16:38:30 -07005904err_close_adapter:
5905 hdd_close_all_adapters( pHddCtx );
5906
5907err_vosstop:
5908 vos_stop(pVosContext);
5909
5910err_vosclose:
5911 status = vos_sched_close( pVosContext );
5912 if (!VOS_IS_STATUS_SUCCESS(status)) {
5913 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5914 "%s: Failed to close VOSS Scheduler", __func__);
5915 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5916 }
5917 vos_close(pVosContext );
5918
Jeff Johnson295189b2012-06-20 16:38:30 -07005919err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005920 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005921
5922err_wdclose:
5923 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5924 vos_watchdog_close(pVosContext);
5925
Jeff Johnson295189b2012-06-20 16:38:30 -07005926err_wiphy_reg:
5927 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005928
5929err_config:
5930 kfree(pHddCtx->cfg_ini);
5931 pHddCtx->cfg_ini= NULL;
5932
5933err_free_hdd_context:
5934 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005935 wiphy_free(wiphy) ;
5936 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005937 VOS_BUG(1);
5938
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005939 if (hdd_is_ssr_required())
5940 {
5941 /* WDI timeout had happened during load, so SSR is needed here */
5942 subsystem_restart("wcnss");
5943 msleep(5000);
5944 }
5945 hdd_set_ssr_required (VOS_FALSE);
5946
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005947 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005948
5949success:
5950 EXIT();
5951 return 0;
5952}
5953
5954/**---------------------------------------------------------------------------
5955
Jeff Johnson32d95a32012-09-10 13:15:23 -07005956 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07005957
Jeff Johnson32d95a32012-09-10 13:15:23 -07005958 This is the driver entry point - called in different timeline depending
5959 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07005960
5961 \param - None
5962
5963 \return - 0 for success, non zero for failure
5964
5965 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07005966static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005967{
5968 VOS_STATUS status;
5969 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005970 struct device *dev = NULL;
5971 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005972#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5973 int max_retries = 0;
5974#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005975
Gopichand Nakkalad0774962013-05-24 11:32:21 +05305976#ifdef WCONN_TRACE_KMSG_LOG_BUFF
5977 vos_wconn_trace_init();
5978#endif
5979
Jeff Johnson295189b2012-06-20 16:38:30 -07005980 ENTER();
5981
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005982#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005983 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07005984#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005985
5986 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
5987 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
5988
5989 //Power Up Libra WLAN card first if not already powered up
5990 status = vos_chipPowerUp(NULL,NULL,NULL);
5991 if (!VOS_IS_STATUS_SUCCESS(status))
5992 {
5993 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
5994 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005995 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005996 }
5997
Jeff Johnson295189b2012-06-20 16:38:30 -07005998#ifdef ANI_BUS_TYPE_PCI
5999
6000 dev = wcnss_wlan_get_device();
6001
6002#endif // ANI_BUS_TYPE_PCI
6003
6004#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07006005
6006#ifdef HAVE_WCNSS_CAL_DOWNLOAD
6007 /* wait until WCNSS driver downloads NV */
6008 while (!wcnss_device_ready() && 5 >= ++max_retries) {
6009 msleep(1000);
6010 }
6011 if (max_retries >= 5) {
6012 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
6013 return -ENODEV;
6014 }
6015#endif
6016
Jeff Johnson295189b2012-06-20 16:38:30 -07006017 dev = wcnss_wlan_get_device();
6018#endif // ANI_BUS_TYPE_PLATFORM
6019
6020
6021 do {
6022 if (NULL == dev) {
6023 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
6024 ret_status = -1;
6025 break;
6026 }
6027
6028#ifdef MEMORY_DEBUG
6029 vos_mem_init();
6030#endif
6031
6032#ifdef TIMER_MANAGER
6033 vos_timer_manager_init();
6034#endif
6035
6036 /* Preopen VOSS so that it is ready to start at least SAL */
6037 status = vos_preOpen(&pVosContext);
6038
6039 if (!VOS_IS_STATUS_SUCCESS(status))
6040 {
6041 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
6042 ret_status = -1;
6043 break;
6044 }
6045
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006046#ifndef MODULE
6047 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
6048 */
6049 hdd_set_conparam((v_UINT_t)con_mode);
6050#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006051
6052 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006053 if (hdd_wlan_startup(dev))
6054 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006055 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006056 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006057 vos_preClose( &pVosContext );
6058 ret_status = -1;
6059 break;
6060 }
6061
6062 /* Cancel the vote for XO Core ON
6063 * This is done here for safety purposes in case we re-initialize without turning
6064 * it OFF in any error scenario.
6065 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006066 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07006067 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006068 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07006069 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6070 {
6071 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
6072 " Power consumed will be high\n");
6073 }
6074 } while (0);
6075
6076 if (0 != ret_status)
6077 {
6078 //Assert Deep sleep signal now to put Libra HW in lowest power state
6079 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6080 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
6081
6082 //Vote off any PMIC voltage supplies
6083 vos_chipPowerDown(NULL, NULL, NULL);
6084#ifdef TIMER_MANAGER
6085 vos_timer_exit();
6086#endif
6087#ifdef MEMORY_DEBUG
6088 vos_mem_exit();
6089#endif
6090
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006091#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006092 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006093#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006094 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
6095 }
6096 else
6097 {
6098 //Send WLAN UP indication to Nlink Service
6099 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
6100
6101 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
6102
6103 }
6104
6105 EXIT();
6106
6107 return ret_status;
6108}
6109
Jeff Johnson32d95a32012-09-10 13:15:23 -07006110/**---------------------------------------------------------------------------
6111
6112 \brief hdd_module_init() - Init Function
6113
6114 This is the driver entry point (invoked when module is loaded using insmod)
6115
6116 \param - None
6117
6118 \return - 0 for success, non zero for failure
6119
6120 --------------------------------------------------------------------------*/
6121#ifdef MODULE
6122static int __init hdd_module_init ( void)
6123{
6124 return hdd_driver_init();
6125}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006126#else /* #ifdef MODULE */
6127static int __init hdd_module_init ( void)
6128{
6129 /* Driver initialization is delayed to fwpath_changed_handler */
6130 return 0;
6131}
Jeff Johnson32d95a32012-09-10 13:15:23 -07006132#endif /* #ifdef MODULE */
6133
Jeff Johnson295189b2012-06-20 16:38:30 -07006134
6135/**---------------------------------------------------------------------------
6136
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006137 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07006138
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006139 This is the driver exit point (invoked when module is unloaded using rmmod
6140 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07006141
6142 \param - None
6143
6144 \return - None
6145
6146 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006147static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006148{
6149 hdd_context_t *pHddCtx = NULL;
6150 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006151 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006152
6153 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
6154
6155 //Get the global vos context
6156 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6157
6158 if(!pVosContext)
6159 {
6160 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
6161 goto done;
6162 }
6163
6164 //Get the HDD context.
6165 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
6166
6167 if(!pHddCtx)
6168 {
6169 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
6170 }
6171 else
6172 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006173 while(isWDresetInProgress()) {
6174 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6175 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07006176 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07006177
6178 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
6179 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6180 "%s:SSR never completed, fatal error", __func__);
6181 VOS_BUG(0);
6182 }
6183 }
6184
Jeff Johnson295189b2012-06-20 16:38:30 -07006185
6186 pHddCtx->isLoadUnloadInProgress = TRUE;
6187 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6188
6189 //Do all the cleanup before deregistering the driver
6190 hdd_wlan_exit(pHddCtx);
6191 }
6192
Jeff Johnson295189b2012-06-20 16:38:30 -07006193 vos_preClose( &pVosContext );
6194
6195#ifdef TIMER_MANAGER
6196 vos_timer_exit();
6197#endif
6198#ifdef MEMORY_DEBUG
6199 vos_mem_exit();
6200#endif
6201
Gopichand Nakkalad0774962013-05-24 11:32:21 +05306202#ifdef WCONN_TRACE_KMSG_LOG_BUFF
6203 vos_wconn_trace_exit();
6204#endif
6205
Jeff Johnson295189b2012-06-20 16:38:30 -07006206done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006207#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006208 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006209#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006210 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
6211}
6212
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006213/**---------------------------------------------------------------------------
6214
6215 \brief hdd_module_exit() - Exit function
6216
6217 This is the driver exit point (invoked when module is unloaded using rmmod)
6218
6219 \param - None
6220
6221 \return - None
6222
6223 --------------------------------------------------------------------------*/
6224static void __exit hdd_module_exit(void)
6225{
6226 hdd_driver_exit();
6227}
6228
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006229#ifdef MODULE
6230static int fwpath_changed_handler(const char *kmessage,
6231 struct kernel_param *kp)
6232{
Jeff Johnson76052702013-04-16 13:55:05 -07006233 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006234}
6235
6236static int con_mode_handler(const char *kmessage,
6237 struct kernel_param *kp)
6238{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07006239 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006240}
6241#else /* #ifdef MODULE */
6242/**---------------------------------------------------------------------------
6243
Jeff Johnson76052702013-04-16 13:55:05 -07006244 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006245
Jeff Johnson76052702013-04-16 13:55:05 -07006246 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006247 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07006248 - invoked when module parameter fwpath is modified from userspace to signal
6249 initializing the WLAN driver or when con_mode is modified from userspace
6250 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006251
6252 \return - 0 for success, non zero for failure
6253
6254 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006255static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006256{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006257 int ret_status;
6258
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006259 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006260 ret_status = hdd_driver_init();
6261 wlan_hdd_inited = ret_status ? 0 : 1;
6262 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006263 }
6264
6265 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07006266
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006267 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07006268
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07006269 ret_status = hdd_driver_init();
6270 wlan_hdd_inited = ret_status ? 0 : 1;
6271 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07006272}
6273
Jeff Johnson295189b2012-06-20 16:38:30 -07006274/**---------------------------------------------------------------------------
6275
Jeff Johnson76052702013-04-16 13:55:05 -07006276 \brief fwpath_changed_handler() - Handler Function
6277
6278 Handle changes to the fwpath parameter
6279
6280 \return - 0 for success, non zero for failure
6281
6282 --------------------------------------------------------------------------*/
6283static int fwpath_changed_handler(const char *kmessage,
6284 struct kernel_param *kp)
6285{
6286 int ret;
6287
6288 ret = param_set_copystring(kmessage, kp);
6289 if (0 == ret)
6290 ret = kickstart_driver();
6291 return ret;
6292}
6293
6294/**---------------------------------------------------------------------------
6295
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006296 \brief con_mode_handler() -
6297
6298 Handler function for module param con_mode when it is changed by userspace
6299 Dynamically linked - do nothing
6300 Statically linked - exit and init driver, as in rmmod and insmod
6301
Jeff Johnson76052702013-04-16 13:55:05 -07006302 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006303
Jeff Johnson76052702013-04-16 13:55:05 -07006304 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006305
6306 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07006307static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006308{
Jeff Johnson76052702013-04-16 13:55:05 -07006309 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006310
Jeff Johnson76052702013-04-16 13:55:05 -07006311 ret = param_set_int(kmessage, kp);
6312 if (0 == ret)
6313 ret = kickstart_driver();
6314 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006315}
6316#endif /* #ifdef MODULE */
6317
6318/**---------------------------------------------------------------------------
6319
Jeff Johnson295189b2012-06-20 16:38:30 -07006320 \brief hdd_get_conparam() -
6321
6322 This is the driver exit point (invoked when module is unloaded using rmmod)
6323
6324 \param - None
6325
6326 \return - tVOS_CON_MODE
6327
6328 --------------------------------------------------------------------------*/
6329tVOS_CON_MODE hdd_get_conparam ( void )
6330{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006331#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07006332 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006333#else
6334 return (tVOS_CON_MODE)curr_con_mode;
6335#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006336}
6337void hdd_set_conparam ( v_UINT_t newParam )
6338{
6339 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006340#ifndef MODULE
6341 curr_con_mode = con_mode;
6342#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006343}
6344/**---------------------------------------------------------------------------
6345
6346 \brief hdd_softap_sta_deauth() - function
6347
6348 This to take counter measure to handle deauth req from HDD
6349
6350 \param - pAdapter - Pointer to the HDD
6351
6352 \param - enable - boolean value
6353
6354 \return - None
6355
6356 --------------------------------------------------------------------------*/
6357
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006358VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07006359{
Jeff Johnson295189b2012-06-20 16:38:30 -07006360 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006361 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07006362
6363 ENTER();
6364
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306365 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006366
6367 //Ignore request to deauth bcmc station
6368 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006369 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006370
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006371 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07006372
6373 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08006374 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07006375}
6376
6377/**---------------------------------------------------------------------------
6378
6379 \brief hdd_softap_sta_disassoc() - function
6380
6381 This to take counter measure to handle deauth req from HDD
6382
6383 \param - pAdapter - Pointer to the HDD
6384
6385 \param - enable - boolean value
6386
6387 \return - None
6388
6389 --------------------------------------------------------------------------*/
6390
6391void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
6392{
6393 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6394
6395 ENTER();
6396
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306397 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006398
6399 //Ignore request to disassoc bcmc station
6400 if( pDestMacAddress[0] & 0x1 )
6401 return;
6402
6403 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
6404}
6405
6406void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
6407{
6408 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
6409
6410 ENTER();
6411
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306412 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006413
6414 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
6415}
6416
Jeff Johnson295189b2012-06-20 16:38:30 -07006417/**---------------------------------------------------------------------------
6418 *
6419 * \brief hdd_get__concurrency_mode() -
6420 *
6421 *
6422 * \param - None
6423 *
6424 * \return - CONCURRENCY MODE
6425 *
6426 * --------------------------------------------------------------------------*/
6427tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6428{
6429 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6430 hdd_context_t *pHddCtx;
6431
6432 if (NULL != pVosContext)
6433 {
6434 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6435 if (NULL != pHddCtx)
6436 {
6437 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6438 }
6439 }
6440
6441 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006442 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006443 return VOS_STA;
6444}
6445
6446/* Decide whether to allow/not the apps power collapse.
6447 * Allow apps power collapse if we are in connected state.
6448 * if not, allow only if we are in IMPS */
6449v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6450{
6451 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006452 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006453 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006454 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6455 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6456 hdd_adapter_t *pAdapter = NULL;
6457 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006458 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006459
Jeff Johnson295189b2012-06-20 16:38:30 -07006460 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6461 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006462
Yathish9f22e662012-12-10 14:21:35 -08006463 concurrent_state = hdd_get_concurrency_mode();
6464
6465#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6466 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6467 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6468 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6469 return TRUE;
6470#endif
6471
Jeff Johnson295189b2012-06-20 16:38:30 -07006472 /*loop through all adapters. TBD fix for Concurrency */
6473 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6474 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6475 {
6476 pAdapter = pAdapterNode->pAdapter;
6477 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6478 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6479 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006480 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006481 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006482 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006483 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6484 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006485 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006486 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006487 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6488 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006489 return FALSE;
6490 }
6491 }
6492 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6493 pAdapterNode = pNext;
6494 }
6495 return TRUE;
6496}
6497
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006498/* Decides whether to send suspend notification to Riva
6499 * if any adapter is in BMPS; then it is required */
6500v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6501{
6502 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6503 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6504
6505 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6506 {
6507 return TRUE;
6508 }
6509 return FALSE;
6510}
6511
Jeff Johnson295189b2012-06-20 16:38:30 -07006512void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6513{
6514 switch(mode)
6515 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006516 case VOS_STA_MODE:
6517 case VOS_P2P_CLIENT_MODE:
6518 case VOS_P2P_GO_MODE:
6519 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006520 pHddCtx->concurrency_mode |= (1 << mode);
6521 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006522 break;
6523 default:
6524 break;
6525
6526 }
6527 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6528 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6529}
6530
6531
6532void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6533{
6534 switch(mode)
6535 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006536 case VOS_STA_MODE:
6537 case VOS_P2P_CLIENT_MODE:
6538 case VOS_P2P_GO_MODE:
6539 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006540 pHddCtx->no_of_sessions[mode]--;
6541 if (!(pHddCtx->no_of_sessions[mode]))
6542 pHddCtx->concurrency_mode &= (~(1 << mode));
6543 break;
6544 default:
6545 break;
6546 }
6547 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6548 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6549}
6550
Jeff Johnsone7245742012-09-05 17:12:55 -07006551/**---------------------------------------------------------------------------
6552 *
6553 * \brief wlan_hdd_restart_init
6554 *
6555 * This function initalizes restart timer/flag. An internal function.
6556 *
6557 * \param - pHddCtx
6558 *
6559 * \return - None
6560 *
6561 * --------------------------------------------------------------------------*/
6562
6563static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6564{
6565 /* Initialize */
6566 pHddCtx->hdd_restart_retries = 0;
6567 atomic_set(&pHddCtx->isRestartInProgress, 0);
6568 vos_timer_init(&pHddCtx->hdd_restart_timer,
6569 VOS_TIMER_TYPE_SW,
6570 wlan_hdd_restart_timer_cb,
6571 pHddCtx);
6572}
6573/**---------------------------------------------------------------------------
6574 *
6575 * \brief wlan_hdd_restart_deinit
6576 *
6577 * This function cleans up the resources used. An internal function.
6578 *
6579 * \param - pHddCtx
6580 *
6581 * \return - None
6582 *
6583 * --------------------------------------------------------------------------*/
6584
6585static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6586{
6587
6588 VOS_STATUS vos_status;
6589 /* Block any further calls */
6590 atomic_set(&pHddCtx->isRestartInProgress, 1);
6591 /* Cleanup */
6592 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6593 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006594 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006595 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6596 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006597 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006598
6599}
6600
6601/**---------------------------------------------------------------------------
6602 *
6603 * \brief wlan_hdd_framework_restart
6604 *
6605 * This function uses a cfg80211 API to start a framework initiated WLAN
6606 * driver module unload/load.
6607 *
6608 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6609 *
6610 *
6611 * \param - pHddCtx
6612 *
6613 * \return - VOS_STATUS_SUCCESS: Success
6614 * VOS_STATUS_E_EMPTY: Adapter is Empty
6615 * VOS_STATUS_E_NOMEM: No memory
6616
6617 * --------------------------------------------------------------------------*/
6618
6619static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6620{
6621 VOS_STATUS status = VOS_STATUS_SUCCESS;
6622 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006623 int len = (sizeof (struct ieee80211_mgmt));
6624 struct ieee80211_mgmt *mgmt = NULL;
6625
6626 /* Prepare the DEAUTH managment frame with reason code */
6627 mgmt = kzalloc(len, GFP_KERNEL);
6628 if(mgmt == NULL)
6629 {
6630 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6631 "%s: memory allocation failed (%d bytes)", __func__, len);
6632 return VOS_STATUS_E_NOMEM;
6633 }
6634 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006635
6636 /* Iterate over all adapters/devices */
6637 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6638 do
6639 {
6640 if( (status == VOS_STATUS_SUCCESS) &&
6641 pAdapterNode &&
6642 pAdapterNode->pAdapter)
6643 {
6644 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6645 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6646 pAdapterNode->pAdapter->dev->name,
6647 pAdapterNode->pAdapter->device_mode,
6648 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006649 /*
6650 * CFG80211 event to restart the driver
6651 *
6652 * 'cfg80211_send_unprot_deauth' sends a
6653 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6654 * of SME(Linux Kernel) state machine.
6655 *
6656 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6657 * the driver.
6658 *
6659 */
6660
6661 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006662 }
6663 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6664 pAdapterNode = pNext;
6665 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6666
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006667
6668 /* Free the allocated management frame */
6669 kfree(mgmt);
6670
Jeff Johnsone7245742012-09-05 17:12:55 -07006671 /* Retry until we unload or reach max count */
6672 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6673 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6674
6675 return status;
6676
6677}
6678/**---------------------------------------------------------------------------
6679 *
6680 * \brief wlan_hdd_restart_timer_cb
6681 *
6682 * Restart timer callback. An internal function.
6683 *
6684 * \param - User data:
6685 *
6686 * \return - None
6687 *
6688 * --------------------------------------------------------------------------*/
6689
6690void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6691{
6692 hdd_context_t *pHddCtx = usrDataForCallback;
6693 wlan_hdd_framework_restart(pHddCtx);
6694 return;
6695
6696}
6697
6698
6699/**---------------------------------------------------------------------------
6700 *
6701 * \brief wlan_hdd_restart_driver
6702 *
6703 * This function sends an event to supplicant to restart the WLAN driver.
6704 *
6705 * This function is called from vos_wlanRestart.
6706 *
6707 * \param - pHddCtx
6708 *
6709 * \return - VOS_STATUS_SUCCESS: Success
6710 * VOS_STATUS_E_EMPTY: Adapter is Empty
6711 * VOS_STATUS_E_ALREADY: Request already in progress
6712
6713 * --------------------------------------------------------------------------*/
6714VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6715{
6716 VOS_STATUS status = VOS_STATUS_SUCCESS;
6717
6718 /* A tight check to make sure reentrancy */
6719 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6720 {
6721 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6722 "%s: WLAN restart is already in progress", __func__);
6723
6724 return VOS_STATUS_E_ALREADY;
6725 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006726 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006727#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006728 wcnss_reset_intr();
6729#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006730
Jeff Johnsone7245742012-09-05 17:12:55 -07006731 return status;
6732}
6733
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07006734/*
6735 * API to find if there is any STA or P2P-Client is connected
6736 */
6737VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
6738{
6739 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
6740}
Jeff Johnsone7245742012-09-05 17:12:55 -07006741
Jeff Johnson295189b2012-06-20 16:38:30 -07006742//Register the module init/exit functions
6743module_init(hdd_module_init);
6744module_exit(hdd_module_exit);
6745
6746MODULE_LICENSE("Dual BSD/GPL");
6747MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6748MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6749
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006750module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6751 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006752
Jeff Johnson76052702013-04-16 13:55:05 -07006753module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006754 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);