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