blob: aea784658bfbbe9fdb0a674264a315df8df6e446 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/*========================================================================
43
44 \file wlan_hdd_main.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
54/**=========================================================================
55
56 EDIT HISTORY FOR FILE
57
58
59 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
61
62
63 $Header:$ $DateTime: $ $Author: $
64
65
66 when who what, where, why
67 -------- --- --------------------------------------------------------
68 04/5/09 Shailender Created module.
69 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
70 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
71 ==========================================================================*/
72
73/*--------------------------------------------------------------------------
74 Include Files
75 ------------------------------------------------------------------------*/
76//#include <wlan_qct_driver.h>
77#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070078#include <vos_api.h>
79#include <vos_sched.h>
80#include <vos_power.h>
81#include <linux/etherdevice.h>
82#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070083#ifdef ANI_BUS_TYPE_PLATFORM
84#include <linux/wcnss_wlan.h>
85#endif //ANI_BUS_TYPE_PLATFORM
86#ifdef ANI_BUS_TYPE_PCI
87#include "wcnss_wlan.h"
88#endif /* ANI_BUS_TYPE_PCI */
89#include <wlan_hdd_tx_rx.h>
90#include <palTimer.h>
91#include <wniApi.h>
92#include <wlan_nlink_srv.h>
93#include <wlan_btc_svc.h>
94#include <wlan_hdd_cfg.h>
95#include <wlan_ptt_sock_svc.h>
96#include <wlan_hdd_wowl.h>
97#include <wlan_hdd_misc.h>
98#include <wlan_hdd_wext.h>
99#ifdef WLAN_BTAMP_FEATURE
100#include <bap_hdd_main.h>
101#include <bapInternal.h>
102#endif // WLAN_BTAMP_FEATURE
103
Jeff Johnson295189b2012-06-20 16:38:30 -0700104#include <linux/wireless.h>
105#include <net/cfg80211.h>
106#include "wlan_hdd_cfg80211.h"
107#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700108#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700109int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include "sapApi.h"
111#include <linux/semaphore.h>
112#include <mach/subsystem_restart.h>
113#include <wlan_hdd_hostapd.h>
114#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700115#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700116#include "wlan_hdd_dev_pwr.h"
117#ifdef WLAN_BTAMP_FEATURE
118#include "bap_hdd_misc.h"
119#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700120#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700121#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800122#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530123#ifdef FEATURE_WLAN_TDLS
124#include "wlan_hdd_tdls.h"
125#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700126
127#ifdef MODULE
128#define WLAN_MODULE_NAME module_name(THIS_MODULE)
129#else
130#define WLAN_MODULE_NAME "wlan"
131#endif
132
133#ifdef TIMER_MANAGER
134#define TIMER_MANAGER_STR " +TIMER_MANAGER"
135#else
136#define TIMER_MANAGER_STR ""
137#endif
138
139#ifdef MEMORY_DEBUG
140#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
141#else
142#define MEMORY_DEBUG_STR ""
143#endif
144
145/* the Android framework expects this param even though we don't use it */
146#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700147static char fwpath_buffer[BUF_LEN];
148static struct kparam_string fwpath = {
149 .string = fwpath_buffer,
150 .maxlen = BUF_LEN,
151};
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700152#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700153static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700154#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700155
Jeff Johnsone7245742012-09-05 17:12:55 -0700156/*
157 * The rate at which the driver sends RESTART event to supplicant
158 * once the function 'vos_wlanRestart()' is called
159 *
160 */
161#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
162#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700163
164/*
165 * Size of Driver command strings from upper layer
166 */
167#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
168#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
169
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800170#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700171static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700172#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700173/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700174static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700175
176//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700177static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
178static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
179static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
180void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800181void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700182
Jeff Johnson295189b2012-06-20 16:38:30 -0700183v_U16_t hdd_select_queue(struct net_device *dev,
184 struct sk_buff *skb);
185
186#ifdef WLAN_FEATURE_PACKET_FILTERING
187static void hdd_set_multicast_list(struct net_device *dev);
188#endif
189
190void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700191int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700192
193extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800194#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
195void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
196static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
197static VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700198static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
199 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
200 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800201#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700202static int hdd_netdev_notifier_call(struct notifier_block * nb,
203 unsigned long state,
204 void *ndev)
205{
206 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700207 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700208 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700209#ifdef WLAN_BTAMP_FEATURE
210 VOS_STATUS status;
211 hdd_context_t *pHddCtx;
212#endif
213
214 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700215 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700216 (strncmp(dev->name, "p2p", 3)))
217 return NOTIFY_DONE;
218
219 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700220 return NOTIFY_DONE;
221
Jeff Johnson295189b2012-06-20 16:38:30 -0700222 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700223 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700224
Jeff Johnson27cee452013-03-27 11:10:24 -0700225 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700226 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800227 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700228 VOS_ASSERT(0);
229 return NOTIFY_DONE;
230 }
231
Jeff Johnson27cee452013-03-27 11:10:24 -0700232 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
233 if (NULL == pHddCtx)
234 {
235 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
236 VOS_ASSERT(0);
237 return NOTIFY_DONE;
238 }
239
240 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
241 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700242
243 switch (state) {
244 case NETDEV_REGISTER:
245 break;
246
247 case NETDEV_UNREGISTER:
248 break;
249
250 case NETDEV_UP:
251 break;
252
253 case NETDEV_DOWN:
254 break;
255
256 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700257 if(TRUE == pAdapter->isLinkUpSvcNeeded)
258 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700259 break;
260
261 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700262 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700263 {
264 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800265 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700266 hdd_abort_mac_scan(pAdapter->pHddCtx);
267 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800268 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700269 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
270 if(!result)
271 {
272 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800273 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700274 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700275 }
276 }
277 else
278 {
279 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700280 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700281 }
282#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700283 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700284 status = WLANBAP_StopAmp();
285 if(VOS_STATUS_SUCCESS != status )
286 {
287 pHddCtx->isAmpAllowed = VOS_TRUE;
288 hddLog(VOS_TRACE_LEVEL_FATAL,
289 "%s: Failed to stop AMP", __func__);
290 }
291 else
292 {
293 //a state m/c implementation in PAL is TBD to avoid this delay
294 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700295 if ( pHddCtx->isAmpAllowed )
296 {
297 WLANBAP_DeregisterFromHCI();
298 pHddCtx->isAmpAllowed = VOS_FALSE;
299 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700300 }
301#endif //WLAN_BTAMP_FEATURE
302 break;
303
304 default:
305 break;
306 }
307
308 return NOTIFY_DONE;
309}
310
311struct notifier_block hdd_netdev_notifier = {
312 .notifier_call = hdd_netdev_notifier_call,
313};
314
315/*---------------------------------------------------------------------------
316 * Function definitions
317 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700318void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
319void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700320//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700321static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700322#ifndef MODULE
323/* current con_mode - used only for statically linked driver
324 * con_mode is changed by userspace to indicate a mode change which will
325 * result in calling the module exit and init functions. The module
326 * exit function will clean up based on the value of con_mode prior to it
327 * being changed by userspace. So curr_con_mode records the current con_mode
328 * for exit when con_mode becomes the next mode for init
329 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700330static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700331#endif
332
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800333/**---------------------------------------------------------------------------
334
335 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
336
337 Called immediately after the cfg.ini is read in order to configure
338 the desired trace levels.
339
340 \param - moduleId - module whose trace level is being configured
341 \param - bitmask - bitmask of log levels to be enabled
342
343 \return - void
344
345 --------------------------------------------------------------------------*/
346static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
347{
348 wpt_tracelevel level;
349
350 /* if the bitmask is the default value, then a bitmask was not
351 specified in cfg.ini, so leave the logging level alone (it
352 will remain at the "compiled in" default value) */
353 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
354 {
355 return;
356 }
357
358 /* a mask was specified. start by disabling all logging */
359 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
360
361 /* now cycle through the bitmask until all "set" bits are serviced */
362 level = VOS_TRACE_LEVEL_FATAL;
363 while (0 != bitmask)
364 {
365 if (bitmask & 1)
366 {
367 vos_trace_setValue(moduleId, level, 1);
368 }
369 level++;
370 bitmask >>= 1;
371 }
372}
373
374
Jeff Johnson295189b2012-06-20 16:38:30 -0700375/**---------------------------------------------------------------------------
376
377 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
378
379 Called immediately after the cfg.ini is read in order to configure
380 the desired trace levels in the WDI.
381
382 \param - moduleId - module whose trace level is being configured
383 \param - bitmask - bitmask of log levels to be enabled
384
385 \return - void
386
387 --------------------------------------------------------------------------*/
388static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
389{
390 wpt_tracelevel level;
391
392 /* if the bitmask is the default value, then a bitmask was not
393 specified in cfg.ini, so leave the logging level alone (it
394 will remain at the "compiled in" default value) */
395 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
396 {
397 return;
398 }
399
400 /* a mask was specified. start by disabling all logging */
401 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
402
403 /* now cycle through the bitmask until all "set" bits are serviced */
404 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
405 while (0 != bitmask)
406 {
407 if (bitmask & 1)
408 {
409 wpalTraceSetLevel(moduleId, level, 1);
410 }
411 level++;
412 bitmask >>= 1;
413 }
414}
Jeff Johnson295189b2012-06-20 16:38:30 -0700415
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530416/*
417 * FUNCTION: wlan_hdd_validate_context
418 * This function is used to check the HDD context
419 */
420int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
421{
422 ENTER();
423
424 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
425 {
426 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
427 "%s: HDD context is Null", __func__);
428 return -ENODEV;
429 }
430
431 if (pHddCtx->isLogpInProgress)
432 {
433 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
434 "%s: LOGP in Progress. Ignore!!!", __func__);
435 return -EAGAIN;
436 }
437
438 if (pHddCtx->isLoadUnloadInProgress)
439 {
440 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
441 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
442 return -EAGAIN;
443 }
444 return 0;
445}
446
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530447void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
448{
449 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
450 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
451 hdd_config_t *cfg_param;
452 eCsrPhyMode phyMode;
453
454 if (NULL == pHddCtx)
455 {
456 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
457 "HDD Context is null !!");
458 return ;
459 }
460
461 cfg_param = pHddCtx->cfg_ini;
462
463 if (NULL == cfg_param)
464 {
465 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
466 "cfg_params not available !!");
467 return ;
468 }
469
470 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
471
472 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
473 {
474 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
475 (eCSR_DOT11_MODE_11ac == phyMode) ||
476 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
477 {
478 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
479 "Setting phymode to 11n!!");
480 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
481 }
482 }
483 else
484 {
485 /*New country Supports 11ac as well resetting value back from .ini*/
486 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
487 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
488 return ;
489 }
490
491 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
492 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
493 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
494 {
495 VOS_STATUS vosStatus;
496
497 // need to issue a disconnect to CSR.
498 INIT_COMPLETION(pAdapter->disconnect_comp_var);
499 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
500 pAdapter->sessionId,
501 eCSR_DISCONNECT_REASON_UNSPECIFIED );
502
503 if (VOS_STATUS_SUCCESS == vosStatus)
504 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
505 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
506
507 }
508}
509
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700510void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
511{
512 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
513 hdd_config_t *cfg_param;
514
515 if (NULL == pHddCtx)
516 {
517 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
518 "HDD Context is null !!");
519 return ;
520 }
521
522 cfg_param = pHddCtx->cfg_ini;
523
524 if (NULL == cfg_param)
525 {
526 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
527 "cfg_params not available !!");
528 return ;
529 }
530
531 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
532 {
533 /*New country doesn't support DFS */
534 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
535 }
536 else
537 {
538 /*New country Supports DFS as well resetting value back from .ini*/
539 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
540 }
541
542}
543
Jeff Johnson295189b2012-06-20 16:38:30 -0700544int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
545{
546 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
547 hdd_priv_data_t priv_data;
548 tANI_U8 *command = NULL;
549 int ret = 0;
550
551 if (NULL == pAdapter)
552 {
553 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700554 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700555 ret = -ENODEV;
556 goto exit;
557 }
558
Jeff Johnsone7245742012-09-05 17:12:55 -0700559 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700560 {
561 ret = -EINVAL;
562 goto exit;
563 }
564
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -0700565 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
566 {
567 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
568 "%s:LOGP in Progress. Ignore!!!", __func__);
569 ret = -EBUSY;
570 goto exit;
571 }
572
Jeff Johnson295189b2012-06-20 16:38:30 -0700573 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
574 {
575 ret = -EFAULT;
576 goto exit;
577 }
578
579 command = kmalloc(priv_data.total_len, GFP_KERNEL);
580 if (!command)
581 {
582 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700583 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700584 ret = -ENOMEM;
585 goto exit;
586 }
587
588 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
589 {
590 ret = -EFAULT;
591 goto exit;
592 }
593
594 if ((SIOCDEVPRIVATE + 1) == cmd)
595 {
596 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
597
598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700599 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700600
601 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
602 {
603 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
604 sizeof(tSirMacAddr)))
605 {
606 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700607 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700608 ret = -EFAULT;
609 }
610 }
Amar Singhal0974e402013-02-12 14:27:46 -0800611 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700612 {
Amar Singhal0974e402013-02-12 14:27:46 -0800613 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700614 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800615
Jeff Johnson295189b2012-06-20 16:38:30 -0700616 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800617
618 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700619 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700620 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800621 "%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 -0700622 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800623 ret = hdd_setBand_helper(dev, ptr);
624 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700625 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
626 {
627 char *country_code;
628
629 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700630
631 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530632 hdd_checkandupdate_phymode(pAdapter, country_code);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700633 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
634 pAdapter, pHddCtx->pvosContext);
635 if( 0 != ret )
636 {
637 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
638 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
639
640 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700641 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800642#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
643 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
644 {
645 tANI_U8 *value = command;
646 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
647 tANI_U8 revision = 0;
648 eHalStatus status = eHAL_STATUS_SUCCESS;
649 v_REGDOMAIN_t regId;
650
651 status = hdd_parse_countryrev(value, countryCode, &revision);
652 if (eHAL_STATUS_SUCCESS != status)
653 {
654 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
655 "%s: Failed to parse country revision information", __func__);
656 ret = -EINVAL;
657 goto exit;
658 }
659
660 /* Validate country code */
661 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
662 if (eHAL_STATUS_SUCCESS != status)
663 {
664 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
665 "%s: Invalid country code %s", __func__, countryCode);
666 ret = -EINVAL;
667 goto exit;
668 }
669
670 /* Validate revision */
671 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
672 {
673 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
674 "%s: Invalid revision %d", __func__, revision);
675 ret = -EINVAL;
676 goto exit;
677 }
678
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700679 hdd_checkandupdate_dfssetting(pAdapter, countryCode);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530680 hdd_checkandupdate_phymode(pAdapter, countryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800681 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
682 pAdapter, pHddCtx->pvosContext);
683 if (0 != ret)
684 {
685 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
686 "%s: SME Change Country code fail ret=%d", __func__, ret);
687 ret = -EINVAL;
688 goto exit;
689 }
690
691 if (0 == strncmp(countryCode, "KR", 2))
692 {
693 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
694 revision);
695 if (eHAL_STATUS_SUCCESS != status)
696 {
697 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
698 "%s: Failed to build valid channel list", __func__);
699 ret = -EINVAL;
700 goto exit;
701 }
702 }
703 }
704#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700705 /*
706 command should be a string having format
707 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
708 */
Amar Singhal0974e402013-02-12 14:27:46 -0800709 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700710 {
Amar Singhal0974e402013-02-12 14:27:46 -0800711 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700712
713 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700714 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700715
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800716 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700717 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800718 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
719 {
720 int suspend = 0;
721 tANI_U8 *ptr = (tANI_U8*)command + 15;
722
723 suspend = *ptr - '0';
724 hdd_set_wlan_suspend_mode(suspend);
725 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800726#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
727 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
728 {
729 tANI_U8 *value = command;
730 int rssi = 0;
731 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
732 eHalStatus status = eHAL_STATUS_SUCCESS;
733
734 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
735 value = value + 15;
736
737 sscanf(value, "%d", &rssi);
738 lookUpThreshold = abs(rssi);
739 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
740 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
741 {
742 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
743 "Neighbor lookup threshold value %d is out of range"
744 " (Min: %d Max: %d)", lookUpThreshold,
745 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
746 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
747 ret = -EINVAL;
748 goto exit;
749 }
750
751 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
752 "%s: Received Command to Set Roam trigger"
753 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
754
755 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
756 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
757 if (eHAL_STATUS_SUCCESS != status)
758 {
759 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
760 "%s: Failed to set roam trigger, try again", __func__);
761 ret = -EPERM;
762 goto exit;
763 }
764
765 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
766 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
767 }
768 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
769 {
770 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
771 int rssi = (-1) * lookUpThreshold;
772 char extra[32];
773 tANI_U8 len = 0;
774
775 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
776 if (copy_to_user(priv_data.buf, &extra, len + 1))
777 {
778 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
779 "%s: failed to copy data to user buffer", __func__);
780 ret = -EFAULT;
781 goto exit;
782 }
783 }
784 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
785 {
786 tANI_U8 *value = command;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700787 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800788 /* input refresh period is in terms of seconds */
789 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
790 value = value + 18;
791 /* Convert the value from ascii to integer */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700792 ret = kstrtou16(value, 10, &neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800793 if (ret < 0)
794 {
795 /* If the input value is greater than max value of datatype, then also
796 kstrtou16 fails */
797 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
798 "%s: kstrtou16 failed ",
799 "Input value may be out of range[%d - %d]",
800 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700801 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
802 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800803 ret = -EINVAL;
804 goto exit;
805 }
806
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700807 neighborEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod * 1000;
808 if ((neighborEmptyScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
809 (neighborEmptyScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800810 {
811 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700812 "Neighbor empty scan results refresh period value %d is out of range"
813 " (Min: %d Max: %d)", neighborEmptyScanRefreshPeriod/1000,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700814 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
815 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800816 ret = -EINVAL;
817 goto exit;
818 }
819
820 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
821 "%s: Received Command to Set roam scan period"
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700822 " (Empty Scan refresh period) = %d", __func__, neighborEmptyScanRefreshPeriod/1000);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800823
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700824 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
825 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800826 }
827 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
828 {
829 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
830 char extra[32];
831 tANI_U8 len = 0;
832
833 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
834 /* Returned value is in units of seconds */
835 if (copy_to_user(priv_data.buf, &extra, len + 1))
836 {
837 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
838 "%s: failed to copy data to user buffer", __func__);
839 ret = -EFAULT;
840 goto exit;
841 }
842 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700843 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
844 {
845 tANI_U8 *value = command;
846 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
847 /* input refresh period is in terms of seconds */
848 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
849 value = value + 25;
850 /* Convert the value from ascii to integer */
851 ret = kstrtou16(value, 10, &neighborScanRefreshPeriod);
852 if (ret < 0)
853 {
854 /* If the input value is greater than max value of datatype, then also
855 kstrtou16 fails */
856 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
857 "%s: kstrtou16 failed ",
858 "Input value may be out of range[%d - %d]",
859 __func__,
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700860 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
861 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700862 ret = -EINVAL;
863 goto exit;
864 }
865
866 neighborScanRefreshPeriod = neighborScanRefreshPeriod * 1000;
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700867 if ((neighborScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
868 (neighborScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700869 {
870 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
871 "Neighbor scan results refresh period value %d is out of range"
872 " (Min: %d Max: %d)", neighborScanRefreshPeriod/1000,
873 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
874 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
875 ret = -EINVAL;
876 goto exit;
877 }
878
879 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
880 "%s: Received Command to Set roam scan refresh period"
881 " (Scan refresh period) = %d", __func__, neighborScanRefreshPeriod/1000);
882
883 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
884 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
885 }
886 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
887 {
888 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
889 char extra[32];
890 tANI_U8 len = 0;
891
892 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
893 /* Returned value is in units of seconds */
894 if (copy_to_user(priv_data.buf, &extra, len + 1))
895 {
896 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
897 "%s: failed to copy data to user buffer", __func__);
898 ret = -EFAULT;
899 goto exit;
900 }
901 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700902#ifdef FEATURE_WLAN_LFR
903 /* SETROAMMODE */
904 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
905 {
906 tANI_U8 *value = command;
907 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
908
909 /* Move pointer to ahead of SETROAMMODE<delimiter> */
910 value = value + SIZE_OF_SETROAMMODE + 1;
911
912 /* Convert the value from ascii to integer */
913 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
914 if (ret < 0)
915 {
916 /* If the input value is greater than max value of datatype, then also
917 kstrtou8 fails */
918 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
919 "%s: kstrtou8 failed range [%d - %d]", __func__,
920 CFG_LFR_FEATURE_ENABLED_MIN,
921 CFG_LFR_FEATURE_ENABLED_MAX);
922 ret = -EINVAL;
923 goto exit;
924 }
925 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
926 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
927 {
928 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
929 "Roam Mode value %d is out of range"
930 " (Min: %d Max: %d)", roamMode,
931 CFG_LFR_FEATURE_ENABLED_MIN,
932 CFG_LFR_FEATURE_ENABLED_MAX);
933 ret = -EINVAL;
934 goto exit;
935 }
936
937 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
938 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
939 /*
940 * Note that
941 * SETROAMMODE 0 is to enable LFR while
942 * SETROAMMODE 1 is to disable LFR, but
943 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
944 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
945 */
946 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
947 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
948 else
949 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
950
951 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
952 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
953 }
954 /* GETROAMMODE */
955 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
956 {
957 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
958 char extra[32];
959 tANI_U8 len = 0;
960
961 /*
962 * roamMode value shall be inverted because the sementics is different.
963 */
964 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
965 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
966 else
967 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
968
969 len = snprintf(extra, sizeof(extra), "%s %d", command, roamMode);
970 if (copy_to_user(priv_data.buf, &extra, len + 1))
971 {
972 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
973 "%s: failed to copy data to user buffer", __func__);
974 ret = -EFAULT;
975 goto exit;
976 }
977 }
978#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -0800979#endif
980#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
981 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
982 {
983 tANI_U8 *value = command;
984 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
985
986 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
987 value = value + 13;
988 /* Convert the value from ascii to integer */
989 ret = kstrtou8(value, 10, &roamRssiDiff);
990 if (ret < 0)
991 {
992 /* If the input value is greater than max value of datatype, then also
993 kstrtou8 fails */
994 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
995 "%s: kstrtou8 failed range [%d - %d]", __func__,
996 CFG_ROAM_RSSI_DIFF_MIN,
997 CFG_ROAM_RSSI_DIFF_MAX);
998 ret = -EINVAL;
999 goto exit;
1000 }
1001
1002 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
1003 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
1004 {
1005 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1006 "Roam rssi diff value %d is out of range"
1007 " (Min: %d Max: %d)", roamRssiDiff,
1008 CFG_ROAM_RSSI_DIFF_MIN,
1009 CFG_ROAM_RSSI_DIFF_MAX);
1010 ret = -EINVAL;
1011 goto exit;
1012 }
1013
1014 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1015 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
1016
1017 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
1018 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
1019 }
1020 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
1021 {
1022 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
1023 char extra[32];
1024 tANI_U8 len = 0;
1025
1026 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
1027 if (copy_to_user(priv_data.buf, &extra, len + 1))
1028 {
1029 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1030 "%s: failed to copy data to user buffer", __func__);
1031 ret = -EFAULT;
1032 goto exit;
1033 }
1034 }
1035#endif
1036#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1037 else if (strncmp(command, "GETBAND", 7) == 0)
1038 {
1039 int band = -1;
1040 char extra[32];
1041 tANI_U8 len = 0;
1042 hdd_getBand_helper(pHddCtx, &band);
1043
1044 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
1045 if (copy_to_user(priv_data.buf, &extra, len + 1))
1046 {
1047 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1048 "%s: failed to copy data to user buffer", __func__);
1049 ret = -EFAULT;
1050 goto exit;
1051 }
1052 }
1053 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
1054 {
1055 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
1056 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
1057 tANI_U8 revision = 0;
1058 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
1059 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
1060 char extra[32] = {0};
1061 tANI_U8 len = 0;
1062
1063 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
1064 {
1065 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1066 "%s: failed to get country code", __func__);
1067 ret = -EFAULT;
1068 goto exit;
1069 }
1070 pBuf[uBufLen] = '\0';
1071 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
1072
1073 if (0 == strncmp(pBuf, "KR", 2))
1074 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
1075 else
1076 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
1077
1078 if (copy_to_user(priv_data.buf, &extra, len + 1))
1079 {
1080 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1081 "%s: failed to copy data to user buffer", __func__);
1082 ret = -EFAULT;
1083 goto exit;
1084 }
1085 }
1086 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1087 {
1088 tANI_U8 *value = command;
1089 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1090 tANI_U8 numChannels = 0;
1091 eHalStatus status = eHAL_STATUS_SUCCESS;
1092
1093 status = hdd_parse_channellist(value, ChannelList, &numChannels);
1094 if (eHAL_STATUS_SUCCESS != status)
1095 {
1096 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1097 "%s: Failed to parse channel list information", __func__);
1098 ret = -EINVAL;
1099 goto exit;
1100 }
1101
1102 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
1103 {
1104 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1105 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
1106 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
1107 ret = -EINVAL;
1108 goto exit;
1109 }
1110 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
1111 numChannels);
1112 if (eHAL_STATUS_SUCCESS != status)
1113 {
1114 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1115 "%s: Failed to update channel list information", __func__);
1116 ret = -EINVAL;
1117 goto exit;
1118 }
1119 }
1120 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
1121 {
1122 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1123 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07001124 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001125 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07001126 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001127
1128 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
1129 ChannelList, &numChannels ))
1130 {
1131 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1132 "%s: failed to get roam scan channel list", __func__);
1133 ret = -EFAULT;
1134 goto exit;
1135 }
1136 /* output channel list is of the format
1137 [Number of roam scan channels][Channel1][Channel2]... */
1138 /* copy the number of channels in the 0th index */
1139 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
1140 for (j = 0; (j < numChannels); j++)
1141 {
1142 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
1143 }
1144
1145 if (copy_to_user(priv_data.buf, &extra, len + 1))
1146 {
1147 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1148 "%s: failed to copy data to user buffer", __func__);
1149 ret = -EFAULT;
1150 goto exit;
1151 }
1152 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001153 else if (strncmp(command, "GETCCXMODE", 10) == 0)
1154 {
1155 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1156 char extra[32];
1157 tANI_U8 len = 0;
1158
1159 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
1160 if (copy_to_user(priv_data.buf, &extra, len + 1))
1161 {
1162 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1163 "%s: failed to copy data to user buffer", __func__);
1164 ret = -EFAULT;
1165 goto exit;
1166 }
1167 }
1168 else if (strncmp(command, "GETOKCMODE", 10) == 0)
1169 {
1170 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
1171 char extra[32];
1172 tANI_U8 len = 0;
1173
1174 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
1175 if (copy_to_user(priv_data.buf, &extra, len + 1))
1176 {
1177 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1178 "%s: failed to copy data to user buffer", __func__);
1179 ret = -EFAULT;
1180 goto exit;
1181 }
1182 }
1183 else if (strncmp(command, "GETFASTROAM", 10) == 0)
1184 {
1185 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1186 char extra[32];
1187 tANI_U8 len = 0;
1188
1189 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
1190 if (copy_to_user(priv_data.buf, &extra, len + 1))
1191 {
1192 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1193 "%s: failed to copy data to user buffer", __func__);
1194 ret = -EFAULT;
1195 goto exit;
1196 }
1197 }
1198 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
1199 {
1200 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1201 char extra[32];
1202 tANI_U8 len = 0;
1203
1204 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
1205 if (copy_to_user(priv_data.buf, &extra, len + 1))
1206 {
1207 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1208 "%s: failed to copy data to user buffer", __func__);
1209 ret = -EFAULT;
1210 goto exit;
1211 }
1212 }
1213 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
1214 {
1215 tANI_U8 *value = command;
1216 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1217
1218 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1219 value = value + 26;
1220 /* Convert the value from ascii to integer */
1221 ret = kstrtou8(value, 10, &minTime);
1222 if (ret < 0)
1223 {
1224 /* If the input value is greater than max value of datatype, then also
1225 kstrtou8 fails */
1226 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1227 "%s: kstrtou8 failed range [%d - %d]", __func__,
1228 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1229 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1230 ret = -EINVAL;
1231 goto exit;
1232 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001233 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1234 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1235 {
1236 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1237 "scan min channel time value %d is out of range"
1238 " (Min: %d Max: %d)", minTime,
1239 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1240 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1241 ret = -EINVAL;
1242 goto exit;
1243 }
1244
1245 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1246 "%s: Received Command to change channel min time = %d", __func__, minTime);
1247
1248 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1249 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1250 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001251 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1252 {
1253 tANI_U8 *value = command;
1254 tANI_U8 channel = 0;
1255 tANI_U8 dwellTime = 0;
1256 tANI_U8 bufLen = 0;
1257 tANI_U8 *buf = NULL;
1258 tSirMacAddr targetApBssid;
1259 eHalStatus status = eHAL_STATUS_SUCCESS;
1260 struct ieee80211_channel chan;
1261 tANI_U8 finalLen = 0;
1262 tANI_U8 *finalBuf = NULL;
1263 tANI_U8 temp = 0;
1264 u64 cookie;
1265 hdd_station_ctx_t *pHddStaCtx = NULL;
1266 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1267
1268 /* if not associated, no need to send action frame */
1269 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1270 {
1271 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1272 ret = -EINVAL;
1273 goto exit;
1274 }
1275
1276 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1277 &dwellTime, &buf, &bufLen);
1278 if (eHAL_STATUS_SUCCESS != status)
1279 {
1280 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1281 "%s: Failed to parse send action frame data", __func__);
1282 ret = -EINVAL;
1283 goto exit;
1284 }
1285
1286 /* if the target bssid is different from currently associated AP,
1287 then no need to send action frame */
1288 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1289 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1290 {
1291 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1292 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001293 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001294 goto exit;
1295 }
1296
1297 /* if the channel number is different from operating channel then
1298 no need to send action frame */
1299 if (channel != pHddStaCtx->conn_info.operationChannel)
1300 {
1301 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1302 "%s: channel(%d) is different from operating channel(%d)",
1303 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1304 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001305 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001306 goto exit;
1307 }
1308 chan.center_freq = sme_ChnToFreq(channel);
1309
1310 finalLen = bufLen + 24;
1311 finalBuf = vos_mem_malloc(finalLen);
1312 if (NULL == finalBuf)
1313 {
1314 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1315 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001316 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001317 goto exit;
1318 }
1319 vos_mem_zero(finalBuf, finalLen);
1320
1321 /* Fill subtype */
1322 temp = SIR_MAC_MGMT_ACTION << 4;
1323 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1324
1325 /* Fill type */
1326 temp = SIR_MAC_MGMT_FRAME;
1327 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1328
1329 /* Fill destination address (bssid of the AP) */
1330 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1331
1332 /* Fill BSSID (STA mac address) */
1333 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1334
1335 /* Fill source address (STA mac address) */
1336 vos_mem_copy(finalBuf + 16, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1337
1338 /* Fill received buffer from 24th address */
1339 vos_mem_copy(finalBuf + 24, buf, bufLen);
1340
Jeff Johnson11c33152013-04-16 17:52:40 -07001341 /* done with the parsed buffer */
1342 vos_mem_free(buf);
1343
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001344 wlan_hdd_action( NULL, dev, &chan, 0, NL80211_CHAN_HT20,
1345 1, dwellTime, finalBuf, finalLen, 1,
1346 1, &cookie );
1347 vos_mem_free(finalBuf);
1348 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001349 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1350 {
1351 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1352 char extra[32];
1353 tANI_U8 len = 0;
1354
1355 /* value is interms of msec */
1356 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1357 if (copy_to_user(priv_data.buf, &extra, len + 1))
1358 {
1359 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1360 "%s: failed to copy data to user buffer", __func__);
1361 ret = -EFAULT;
1362 goto exit;
1363 }
1364 }
1365 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1366 {
1367 tANI_U8 *value = command;
1368 tANI_U8 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
1369
1370 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1371 value = value + 19;
1372 /* Convert the value from ascii to integer */
1373 ret = kstrtou8(value, 10, &maxTime);
1374 if (ret < 0)
1375 {
1376 /* If the input value is greater than max value of datatype, then also
1377 kstrtou8 fails */
1378 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1379 "%s: kstrtou8 failed range [%d - %d]", __func__,
1380 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1381 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1382 ret = -EINVAL;
1383 goto exit;
1384 }
1385
1386 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1387 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1388 {
1389 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1390 "lfr mode value %d is out of range"
1391 " (Min: %d Max: %d)", maxTime,
1392 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1393 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1394 ret = -EINVAL;
1395 goto exit;
1396 }
1397
1398 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1399 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1400
1401 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
1402 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1403 }
1404 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1405 {
1406 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1407 char extra[32];
1408 tANI_U8 len = 0;
1409
1410 /* value is interms of msec */
1411 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1412 if (copy_to_user(priv_data.buf, &extra, len + 1))
1413 {
1414 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1415 "%s: failed to copy data to user buffer", __func__);
1416 ret = -EFAULT;
1417 goto exit;
1418 }
1419 }
1420 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1421 {
1422 tANI_U8 *value = command;
1423 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1424
1425 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1426 value = value + 16;
1427 /* Convert the value from ascii to integer */
1428 ret = kstrtou16(value, 10, &val);
1429 if (ret < 0)
1430 {
1431 /* If the input value is greater than max value of datatype, then also
1432 kstrtou16 fails */
1433 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1434 "%s: kstrtou16 failed range [%d - %d]", __func__,
1435 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1436 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1437 ret = -EINVAL;
1438 goto exit;
1439 }
1440
1441 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1442 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1443 {
1444 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1445 "scan home time value %d is out of range"
1446 " (Min: %d Max: %d)", val,
1447 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1448 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1449 ret = -EINVAL;
1450 goto exit;
1451 }
1452
1453 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1454 "%s: Received Command to change scan home time = %d", __func__, val);
1455
1456 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1457 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1458 }
1459 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1460 {
1461 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1462 char extra[32];
1463 tANI_U8 len = 0;
1464
1465 /* value is interms of msec */
1466 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1467 if (copy_to_user(priv_data.buf, &extra, len + 1))
1468 {
1469 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1470 "%s: failed to copy data to user buffer", __func__);
1471 ret = -EFAULT;
1472 goto exit;
1473 }
1474 }
1475 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1476 {
1477 tANI_U8 *value = command;
1478 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1479
1480 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1481 value = value + 17;
1482 /* Convert the value from ascii to integer */
1483 ret = kstrtou8(value, 10, &val);
1484 if (ret < 0)
1485 {
1486 /* If the input value is greater than max value of datatype, then also
1487 kstrtou8 fails */
1488 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1489 "%s: kstrtou8 failed range [%d - %d]", __func__,
1490 CFG_ROAM_INTRA_BAND_MIN,
1491 CFG_ROAM_INTRA_BAND_MAX);
1492 ret = -EINVAL;
1493 goto exit;
1494 }
1495
1496 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1497 (val > CFG_ROAM_INTRA_BAND_MAX))
1498 {
1499 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1500 "intra band mode value %d is out of range"
1501 " (Min: %d Max: %d)", val,
1502 CFG_ROAM_INTRA_BAND_MIN,
1503 CFG_ROAM_INTRA_BAND_MAX);
1504 ret = -EINVAL;
1505 goto exit;
1506 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001507 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1508 "%s: Received Command to change intra band = %d", __func__, val);
1509
1510 pHddCtx->cfg_ini->nRoamIntraBand = val;
1511 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1512 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001513 else if (strncmp(command, "SETWESMODE", 10) == 0)
1514 {
1515 tANI_U8 *value = command;
1516 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
1517
1518 /* Move pointer to ahead of SETWESMODE<delimiter> */
1519 value = value + 11;
1520 /* Convert the value from ascii to integer */
1521 ret = kstrtou8(value, 10, &wesMode);
1522 if (ret < 0)
1523 {
1524 /* If the input value is greater than max value of datatype, then also
1525 kstrtou8 fails */
1526 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1527 "%s: kstrtou8 failed range [%d - %d]", __func__,
1528 CFG_ENABLE_WES_MODE_NAME_MIN,
1529 CFG_ENABLE_WES_MODE_NAME_MAX);
1530 ret = -EINVAL;
1531 goto exit;
1532 }
1533
1534 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
1535 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
1536 {
1537 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1538 "WES Mode value %d is out of range"
1539 " (Min: %d Max: %d)", wesMode,
1540 CFG_ENABLE_WES_MODE_NAME_MIN,
1541 CFG_ENABLE_WES_MODE_NAME_MAX);
1542 ret = -EINVAL;
1543 goto exit;
1544 }
1545 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1546 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
1547
1548 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
1549 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
1550 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001551 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1552 {
1553 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1554 char extra[32];
1555 tANI_U8 len = 0;
1556
1557 /* value is interms of msec */
1558 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1559 if (copy_to_user(priv_data.buf, &extra, len + 1))
1560 {
1561 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1562 "%s: failed to copy data to user buffer", __func__);
1563 ret = -EFAULT;
1564 goto exit;
1565 }
1566 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001567 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
1568 {
1569 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
1570 char extra[32];
1571 tANI_U8 len = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001572
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001573 len = snprintf(extra, sizeof(extra), "%s %d", command, wesMode);
1574 if (copy_to_user(priv_data.buf, &extra, len + 1))
1575 {
1576 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1577 "%s: failed to copy data to user buffer", __func__);
1578 ret = -EFAULT;
1579 goto exit;
1580 }
1581 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001582#endif
1583#ifdef FEATURE_WLAN_LFR
1584 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1585 {
1586 tANI_U8 *value = command;
1587 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1588
1589 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1590 value = value + 12;
1591 /* Convert the value from ascii to integer */
1592 ret = kstrtou8(value, 10, &lfrMode);
1593 if (ret < 0)
1594 {
1595 /* If the input value is greater than max value of datatype, then also
1596 kstrtou8 fails */
1597 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1598 "%s: kstrtou8 failed range [%d - %d]", __func__,
1599 CFG_LFR_FEATURE_ENABLED_MIN,
1600 CFG_LFR_FEATURE_ENABLED_MAX);
1601 ret = -EINVAL;
1602 goto exit;
1603 }
1604
1605 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1606 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1607 {
1608 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1609 "lfr mode value %d is out of range"
1610 " (Min: %d Max: %d)", lfrMode,
1611 CFG_LFR_FEATURE_ENABLED_MIN,
1612 CFG_LFR_FEATURE_ENABLED_MAX);
1613 ret = -EINVAL;
1614 goto exit;
1615 }
1616
1617 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1618 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1619
1620 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1621 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1622 }
1623#endif
1624#ifdef WLAN_FEATURE_VOWIFI_11R
1625 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1626 {
1627 tANI_U8 *value = command;
1628 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1629
1630 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1631 value = value + 18;
1632 /* Convert the value from ascii to integer */
1633 ret = kstrtou8(value, 10, &ft);
1634 if (ret < 0)
1635 {
1636 /* If the input value is greater than max value of datatype, then also
1637 kstrtou8 fails */
1638 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1639 "%s: kstrtou8 failed range [%d - %d]", __func__,
1640 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1641 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1642 ret = -EINVAL;
1643 goto exit;
1644 }
1645
1646 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1647 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1648 {
1649 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1650 "ft mode value %d is out of range"
1651 " (Min: %d Max: %d)", ft,
1652 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1653 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1654 ret = -EINVAL;
1655 goto exit;
1656 }
1657
1658 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1659 "%s: Received Command to change ft mode = %d", __func__, ft);
1660
1661 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1662 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1663 }
1664#endif
1665#ifdef FEATURE_WLAN_CCX
1666 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1667 {
1668 tANI_U8 *value = command;
1669 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1670
1671 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1672 value = value + 11;
1673 /* Convert the value from ascii to integer */
1674 ret = kstrtou8(value, 10, &ccxMode);
1675 if (ret < 0)
1676 {
1677 /* If the input value is greater than max value of datatype, then also
1678 kstrtou8 fails */
1679 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1680 "%s: kstrtou8 failed range [%d - %d]", __func__,
1681 CFG_CCX_FEATURE_ENABLED_MIN,
1682 CFG_CCX_FEATURE_ENABLED_MAX);
1683 ret = -EINVAL;
1684 goto exit;
1685 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001686 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1687 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1688 {
1689 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1690 "Ccx mode value %d is out of range"
1691 " (Min: %d Max: %d)", ccxMode,
1692 CFG_CCX_FEATURE_ENABLED_MIN,
1693 CFG_CCX_FEATURE_ENABLED_MAX);
1694 ret = -EINVAL;
1695 goto exit;
1696 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001697 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1698 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1699
1700 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1701 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1702 }
1703#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001704 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1705 {
1706 tANI_U8 *value = command;
1707 tANI_BOOLEAN roamScanControl = 0;
1708
1709 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1710 value = value + 19;
1711 /* Convert the value from ascii to integer */
1712 ret = kstrtou8(value, 10, &roamScanControl);
1713 if (ret < 0)
1714 {
1715 /* If the input value is greater than max value of datatype, then also
1716 kstrtou8 fails */
1717 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1718 "%s: kstrtou8 failed ", __func__);
1719 ret = -EINVAL;
1720 goto exit;
1721 }
1722
1723 if (0 != roamScanControl)
1724 {
1725 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1726 "roam scan control invalid value = %d",
1727 roamScanControl);
1728 ret = -EINVAL;
1729 goto exit;
1730 }
1731 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1732 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1733
1734 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1735 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001736#ifdef FEATURE_WLAN_OKC
1737 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1738 {
1739 tANI_U8 *value = command;
1740 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1741
1742 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1743 value = value + 11;
1744 /* Convert the value from ascii to integer */
1745 ret = kstrtou8(value, 10, &okcMode);
1746 if (ret < 0)
1747 {
1748 /* If the input value is greater than max value of datatype, then also
1749 kstrtou8 fails */
1750 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1751 "%s: kstrtou8 failed range [%d - %d]", __func__,
1752 CFG_OKC_FEATURE_ENABLED_MIN,
1753 CFG_OKC_FEATURE_ENABLED_MAX);
1754 ret = -EINVAL;
1755 goto exit;
1756 }
1757
1758 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1759 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1760 {
1761 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1762 "Okc mode value %d is out of range"
1763 " (Min: %d Max: %d)", okcMode,
1764 CFG_OKC_FEATURE_ENABLED_MIN,
1765 CFG_OKC_FEATURE_ENABLED_MAX);
1766 ret = -EINVAL;
1767 goto exit;
1768 }
1769
1770 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1771 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1772
1773 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1774 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001775 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1776 {
1777 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1778 char extra[32];
1779 tANI_U8 len = 0;
1780
1781 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1782 if (copy_to_user(priv_data.buf, &extra, len + 1))
1783 {
1784 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1785 "%s: failed to copy data to user buffer", __func__);
1786 ret = -EFAULT;
1787 goto exit;
1788 }
1789 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001790#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001791 else {
1792 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
1793 __func__, command);
1794 }
1795
Jeff Johnson295189b2012-06-20 16:38:30 -07001796 }
1797exit:
1798 if (command)
1799 {
1800 kfree(command);
1801 }
1802 return ret;
1803}
1804
Srinivas Girigowdade697412013-02-14 16:31:48 -08001805#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1806void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
1807{
1808 eCsrBand band = -1;
1809 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
1810 switch (band)
1811 {
1812 case eCSR_BAND_ALL:
1813 *pBand = WLAN_HDD_UI_BAND_AUTO;
1814 break;
1815
1816 case eCSR_BAND_24:
1817 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
1818 break;
1819
1820 case eCSR_BAND_5G:
1821 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
1822 break;
1823
1824 default:
1825 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
1826 *pBand = -1;
1827 break;
1828 }
1829}
1830
1831/**---------------------------------------------------------------------------
1832
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001833 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
1834
1835 This function parses the send action frame data passed in the format
1836 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
1837
1838 \param - pValue Pointer to input country code revision
1839 \param - pTargetApBssid Pointer to target Ap bssid
1840 \param - pChannel Pointer to the Target AP channel
1841 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
1842 \param - pBuf Pointer to data
1843 \param - pBufLen Pointer to data length
1844
1845 \return - 0 for success non-zero for failure
1846
1847 --------------------------------------------------------------------------*/
1848VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
1849 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
1850{
1851 tANI_U8 *inPtr = pValue;
1852 tANI_U8 *dataEnd;
1853 int tempInt;
1854 int j = 0;
1855 int i = 0;
1856 int v = 0;
1857 tANI_U8 tempBuf[32];
1858 tANI_U8 tempByte = 0;
1859
1860 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1861 /*no argument after the command*/
1862 if (NULL == inPtr)
1863 {
1864 return -EINVAL;
1865 }
1866
1867 /*no space after the command*/
1868 else if (SPACE_ASCII_VALUE != *inPtr)
1869 {
1870 return -EINVAL;
1871 }
1872
1873 /*removing empty spaces*/
1874 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1875
1876 /*no argument followed by spaces*/
1877 if ('\0' == *inPtr)
1878 {
1879 return -EINVAL;
1880 }
1881
1882 /*getting the first argument ie the target AP bssid */
1883 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
1884 {
1885 return -EINVAL;
1886 }
1887 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
1888 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
1889 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
1890
1891 /* point to the next argument */
1892 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1893 /*no argument after the command*/
1894 if (NULL == inPtr) return -EINVAL;
1895
1896 /*removing empty spaces*/
1897 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1898
1899 /*no argument followed by spaces*/
1900 if ('\0' == *inPtr)
1901 {
1902 return -EINVAL;
1903 }
1904
1905 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07001906 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001907 v = kstrtos32(tempBuf, 10, &tempInt);
1908 if ( v < 0) return -EINVAL;
1909
1910 *pChannel = tempInt;
1911
1912 /* point to the next argument */
1913 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1914 /*no argument after the command*/
1915 if (NULL == inPtr) return -EINVAL;
1916 /*removing empty spaces*/
1917 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1918
1919 /*no argument followed by spaces*/
1920 if ('\0' == *inPtr)
1921 {
1922 return -EINVAL;
1923 }
1924
1925 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07001926 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001927 v = kstrtos32(tempBuf, 10, &tempInt);
1928 if ( v < 0) return -EINVAL;
1929
1930 *pDwellTime = tempInt;
1931
1932 /* point to the next argument */
1933 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1934 /*no argument after the command*/
1935 if (NULL == inPtr) return -EINVAL;
1936 /*removing empty spaces*/
1937 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1938
1939 /*no argument followed by spaces*/
1940 if ('\0' == *inPtr)
1941 {
1942 return -EINVAL;
1943 }
1944
1945 /* find the length of data */
1946 dataEnd = inPtr;
1947 while(('\0' != *dataEnd) )
1948 {
1949 dataEnd++;
1950 ++(*pBufLen);
1951 }
1952 if ( *pBufLen <= 0) return -EINVAL;
1953
1954 *pBuf = vos_mem_malloc(sizeof(*pBufLen));
1955 if (NULL == *pBuf)
1956 {
1957 hddLog(VOS_TRACE_LEVEL_FATAL,
1958 "%s: vos_mem_alloc failed ", __func__);
1959 return -EINVAL;
1960 }
1961
1962 /* the buffer received from the upper layer is character buffer,
1963 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
1964 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
1965 and f0 in 3rd location */
1966 for (i = 0, j = 0; j < *pBufLen; j += 2)
1967 {
1968 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
1969 (*pBuf)[i++] = tempByte;
1970 }
1971 *pBufLen = i;
1972 return VOS_STATUS_SUCCESS;
1973}
1974
1975#endif
1976/**---------------------------------------------------------------------------
1977
Srinivas Girigowdade697412013-02-14 16:31:48 -08001978 \brief hdd_parse_countryrev() - HDD Parse country code revision
1979
1980 This function parses the country code revision passed in the format
1981 SETCOUNTRYREV<space><Country code><space>revision
1982
1983 \param - pValue Pointer to input country code revision
1984 \param - pCountryCode Pointer to local output array to record country code
1985 \param - pRevision Pointer to store revision integer number
1986
1987 \return - 0 for success non-zero for failure
1988
1989 --------------------------------------------------------------------------*/
1990VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
1991{
1992 tANI_U8 *inPtr = pValue;
1993 int tempInt;
1994
1995 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1996 /*no argument after the command*/
1997 if (NULL == inPtr)
1998 {
1999 return -EINVAL;
2000 }
2001
2002 /*no space after the command*/
2003 else if (SPACE_ASCII_VALUE != *inPtr)
2004 {
2005 return -EINVAL;
2006 }
2007
2008 /*removing empty spaces*/
2009 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
2010
2011 /*no argument followed by spaces*/
2012 if ('\0' == *inPtr)
2013 {
2014 return -EINVAL;
2015 }
2016
2017 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07002018 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002019
2020 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2021 "Country code is : %s", pCountryCode);
2022
2023 /*inPtr pointing to the beginning of first space after country code */
2024 inPtr = strpbrk( inPtr, " " );
2025 /*no revision number after the country code argument */
2026 if (NULL == inPtr)
2027 {
2028 return -EINVAL;
2029 }
2030
2031 inPtr++;
2032
2033 /*removing empty space*/
2034 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
2035
2036 /*no channel list after the number of channels argument and spaces*/
2037 if (0 == strncmp(pCountryCode, "KR", 2))
2038 {
2039 if ('\0' == *inPtr)
2040 {
2041 return -EINVAL;
2042 }
2043
2044 sscanf(inPtr, "%d", &tempInt);
2045 *pRevision = tempInt;
2046 }
2047 else
2048 {
2049 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2050 "Revision input is required only for Country KR");
2051 return -EINVAL;
2052 }
2053 return VOS_STATUS_SUCCESS;
2054}
2055
2056/**---------------------------------------------------------------------------
2057
2058 \brief hdd_parse_channellist() - HDD Parse channel list
2059
2060 This function parses the channel list passed in the format
2061 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002062 if the Number of channels (N) does not match with the actual number of channels passed
2063 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
2064 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
2065 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
2066 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08002067
2068 \param - pValue Pointer to input channel list
2069 \param - ChannelList Pointer to local output array to record channel list
2070 \param - pNumChannels Pointer to number of roam scan channels
2071
2072 \return - 0 for success non-zero for failure
2073
2074 --------------------------------------------------------------------------*/
2075VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
2076{
2077 tANI_U8 *inPtr = pValue;
2078 int tempInt;
2079 int j = 0;
2080 int v = 0;
2081 char buf[32];
2082
2083 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2084 /*no argument after the command*/
2085 if (NULL == inPtr)
2086 {
2087 return -EINVAL;
2088 }
2089
2090 /*no space after the command*/
2091 else if (SPACE_ASCII_VALUE != *inPtr)
2092 {
2093 return -EINVAL;
2094 }
2095
2096 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002097 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002098
2099 /*no argument followed by spaces*/
2100 if ('\0' == *inPtr)
2101 {
2102 return -EINVAL;
2103 }
2104
2105 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07002106 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002107 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002108 if ((v < 0) ||
2109 (tempInt <= 0) ||
2110 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
2111 {
2112 return -EINVAL;
2113 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002114
2115 *pNumChannels = tempInt;
2116
2117 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2118 "Number of channels are: %d", *pNumChannels);
2119
2120 for (j = 0; j < (*pNumChannels); j++)
2121 {
2122 /*inPtr pointing to the beginning of first space after number of channels*/
2123 inPtr = strpbrk( inPtr, " " );
2124 /*no channel list after the number of channels argument*/
2125 if (NULL == inPtr)
2126 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002127 if (0 != j)
2128 {
2129 *pNumChannels = j;
2130 return VOS_STATUS_SUCCESS;
2131 }
2132 else
2133 {
2134 return -EINVAL;
2135 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002136 }
2137
2138 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002139 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002140
2141 /*no channel list after the number of channels argument and spaces*/
2142 if ( '\0' == *inPtr )
2143 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07002144 if (0 != j)
2145 {
2146 *pNumChannels = j;
2147 return VOS_STATUS_SUCCESS;
2148 }
2149 else
2150 {
2151 return -EINVAL;
2152 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002153 }
2154
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002155 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002156 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07002157 if ((v < 0) ||
2158 (tempInt <= 0) ||
2159 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
2160 {
2161 return -EINVAL;
2162 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002163 pChannelList[j] = tempInt;
2164
2165 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
2166 "Channel %d added to preferred channel list",
2167 pChannelList[j] );
2168 }
2169
Srinivas Girigowdade697412013-02-14 16:31:48 -08002170 return VOS_STATUS_SUCCESS;
2171}
2172
Jeff Johnson295189b2012-06-20 16:38:30 -07002173/**---------------------------------------------------------------------------
2174
2175 \brief hdd_open() - HDD Open function
2176
2177 This is called in response to ifconfig up
2178
2179 \param - dev Pointer to net_device structure
2180
2181 \return - 0 for success non-zero for failure
2182
2183 --------------------------------------------------------------------------*/
2184int hdd_open (struct net_device *dev)
2185{
2186 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2187 hdd_context_t *pHddCtx;
2188 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2189 VOS_STATUS status;
2190 v_BOOL_t in_standby = TRUE;
2191
2192 if (NULL == pAdapter)
2193 {
2194 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002195 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002196 return -ENODEV;
2197 }
2198
2199 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2200 if (NULL == pHddCtx)
2201 {
2202 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002203 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002204 return -ENODEV;
2205 }
2206
2207 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2208 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2209 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002210 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2211 {
2212 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302213 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002214 in_standby = FALSE;
2215 break;
2216 }
2217 else
2218 {
2219 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2220 pAdapterNode = pNext;
2221 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002222 }
2223
2224 if (TRUE == in_standby)
2225 {
2226 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2227 {
2228 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2229 "wlan out of power save", __func__);
2230 return -EINVAL;
2231 }
2232 }
2233
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002234 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002235 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2236 {
2237 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002238 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002239 /* Enable TX queues only when we are connected */
2240 netif_tx_start_all_queues(dev);
2241 }
2242
2243 return 0;
2244}
2245
2246int hdd_mon_open (struct net_device *dev)
2247{
2248 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2249
2250 if(pAdapter == NULL) {
2251 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002252 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002253 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002254 }
2255
2256 netif_start_queue(dev);
2257
2258 return 0;
2259}
2260/**---------------------------------------------------------------------------
2261
2262 \brief hdd_stop() - HDD stop function
2263
2264 This is called in response to ifconfig down
2265
2266 \param - dev Pointer to net_device structure
2267
2268 \return - 0 for success non-zero for failure
2269
2270 --------------------------------------------------------------------------*/
2271
2272int hdd_stop (struct net_device *dev)
2273{
2274 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2275 hdd_context_t *pHddCtx;
2276 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2277 VOS_STATUS status;
2278 v_BOOL_t enter_standby = TRUE;
2279
2280 ENTER();
2281
2282 if (NULL == pAdapter)
2283 {
2284 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002285 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002286 return -ENODEV;
2287 }
2288
2289 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2290 if (NULL == pHddCtx)
2291 {
2292 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002293 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002294 return -ENODEV;
2295 }
2296
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002297 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002298 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2299 netif_tx_disable(pAdapter->dev);
2300 netif_carrier_off(pAdapter->dev);
2301
2302
2303 /* SoftAP ifaces should never go in power save mode
2304 making sure same here. */
2305 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2306 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002307 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002308 )
2309 {
2310 /* SoftAP mode, so return from here */
2311 EXIT();
2312 return 0;
2313 }
2314
2315 /* Find if any iface is up then
2316 if any iface is up then can't put device to sleep/ power save mode. */
2317 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2318 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2319 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002320 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2321 {
2322 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302323 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002324 enter_standby = FALSE;
2325 break;
2326 }
2327 else
2328 {
2329 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2330 pAdapterNode = pNext;
2331 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002332 }
2333
2334 if (TRUE == enter_standby)
2335 {
2336 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2337 "entering standby", __func__);
2338 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2339 {
2340 /*log and return success*/
2341 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2342 "wlan in power save", __func__);
2343 }
2344 }
2345
2346 EXIT();
2347 return 0;
2348}
2349
2350/**---------------------------------------------------------------------------
2351
2352 \brief hdd_uninit() - HDD uninit function
2353
2354 This is called during the netdev unregister to uninitialize all data
2355associated with the device
2356
2357 \param - dev Pointer to net_device structure
2358
2359 \return - void
2360
2361 --------------------------------------------------------------------------*/
2362static void hdd_uninit (struct net_device *dev)
2363{
2364 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2365
2366 ENTER();
2367
2368 do
2369 {
2370 if (NULL == pAdapter)
2371 {
2372 hddLog(VOS_TRACE_LEVEL_FATAL,
2373 "%s: NULL pAdapter", __func__);
2374 break;
2375 }
2376
2377 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2378 {
2379 hddLog(VOS_TRACE_LEVEL_FATAL,
2380 "%s: Invalid magic", __func__);
2381 break;
2382 }
2383
2384 if (NULL == pAdapter->pHddCtx)
2385 {
2386 hddLog(VOS_TRACE_LEVEL_FATAL,
2387 "%s: NULL pHddCtx", __func__);
2388 break;
2389 }
2390
2391 if (dev != pAdapter->dev)
2392 {
2393 hddLog(VOS_TRACE_LEVEL_FATAL,
2394 "%s: Invalid device reference", __func__);
2395 /* we haven't validated all cases so let this go for now */
2396 }
2397
2398 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2399
2400 /* after uninit our adapter structure will no longer be valid */
2401 pAdapter->dev = NULL;
2402 pAdapter->magic = 0;
2403 } while (0);
2404
2405 EXIT();
2406}
2407
2408/**---------------------------------------------------------------------------
2409
2410 \brief hdd_release_firmware() -
2411
2412 This function calls the release firmware API to free the firmware buffer.
2413
2414 \param - pFileName Pointer to the File Name.
2415 pCtx - Pointer to the adapter .
2416
2417
2418 \return - 0 for success, non zero for failure
2419
2420 --------------------------------------------------------------------------*/
2421
2422VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2423{
2424 VOS_STATUS status = VOS_STATUS_SUCCESS;
2425 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2426 ENTER();
2427
2428
2429 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2430
2431 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2432
2433 if(pHddCtx->fw) {
2434 release_firmware(pHddCtx->fw);
2435 pHddCtx->fw = NULL;
2436 }
2437 else
2438 status = VOS_STATUS_E_FAILURE;
2439 }
2440 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2441 if(pHddCtx->nv) {
2442 release_firmware(pHddCtx->nv);
2443 pHddCtx->nv = NULL;
2444 }
2445 else
2446 status = VOS_STATUS_E_FAILURE;
2447
2448 }
2449
2450 EXIT();
2451 return status;
2452}
2453
2454/**---------------------------------------------------------------------------
2455
2456 \brief hdd_request_firmware() -
2457
2458 This function reads the firmware file using the request firmware
2459 API and returns the the firmware data and the firmware file size.
2460
2461 \param - pfileName - Pointer to the file name.
2462 - pCtx - Pointer to the adapter .
2463 - ppfw_data - Pointer to the pointer of the firmware data.
2464 - pSize - Pointer to the file size.
2465
2466 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2467
2468 --------------------------------------------------------------------------*/
2469
2470
2471VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2472{
2473 int status;
2474 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2475 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2476 ENTER();
2477
2478 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2479
2480 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2481
2482 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2483 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2484 __func__, pfileName);
2485 retval = VOS_STATUS_E_FAILURE;
2486 }
2487
2488 else {
2489 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2490 *pSize = pHddCtx->fw->size;
2491 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2492 __func__, *pSize);
2493 }
2494 }
2495 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2496
2497 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2498
2499 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2500 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2501 __func__, pfileName);
2502 retval = VOS_STATUS_E_FAILURE;
2503 }
2504
2505 else {
2506 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2507 *pSize = pHddCtx->nv->size;
2508 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2509 __func__, *pSize);
2510 }
2511 }
2512
2513 EXIT();
2514 return retval;
2515}
2516/**---------------------------------------------------------------------------
2517 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2518
2519 This is the function invoked by SME to inform the result of a full power
2520 request issued by HDD
2521
2522 \param - callbackcontext - Pointer to cookie
2523 status - result of request
2524
2525 \return - None
2526
2527--------------------------------------------------------------------------*/
2528void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2529{
2530 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2531
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002532 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002533 if(&pHddCtx->full_pwr_comp_var)
2534 {
2535 complete(&pHddCtx->full_pwr_comp_var);
2536 }
2537}
2538
2539/**---------------------------------------------------------------------------
2540
2541 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2542
2543 This is the function invoked by SME to inform the result of BMPS
2544 request issued by HDD
2545
2546 \param - callbackcontext - Pointer to cookie
2547 status - result of request
2548
2549 \return - None
2550
2551--------------------------------------------------------------------------*/
2552void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2553{
2554
2555 struct completion *completion_var = (struct completion*) callbackContext;
2556
2557 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2558 if(completion_var != NULL)
2559 {
2560 complete(completion_var);
2561 }
2562}
2563
2564/**---------------------------------------------------------------------------
2565
2566 \brief hdd_get_cfg_file_size() -
2567
2568 This function reads the configuration file using the request firmware
2569 API and returns the configuration file size.
2570
2571 \param - pCtx - Pointer to the adapter .
2572 - pFileName - Pointer to the file name.
2573 - pBufSize - Pointer to the buffer size.
2574
2575 \return - 0 for success, non zero for failure
2576
2577 --------------------------------------------------------------------------*/
2578
2579VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2580{
2581 int status;
2582 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2583
2584 ENTER();
2585
2586 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2587
2588 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2589 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2590 status = VOS_STATUS_E_FAILURE;
2591 }
2592 else {
2593 *pBufSize = pHddCtx->fw->size;
2594 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2595 release_firmware(pHddCtx->fw);
2596 pHddCtx->fw = NULL;
2597 }
2598
2599 EXIT();
2600 return VOS_STATUS_SUCCESS;
2601}
2602
2603/**---------------------------------------------------------------------------
2604
2605 \brief hdd_read_cfg_file() -
2606
2607 This function reads the configuration file using the request firmware
2608 API and returns the cfg data and the buffer size of the configuration file.
2609
2610 \param - pCtx - Pointer to the adapter .
2611 - pFileName - Pointer to the file name.
2612 - pBuffer - Pointer to the data buffer.
2613 - pBufSize - Pointer to the buffer size.
2614
2615 \return - 0 for success, non zero for failure
2616
2617 --------------------------------------------------------------------------*/
2618
2619VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2620 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2621{
2622 int status;
2623 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2624
2625 ENTER();
2626
2627 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2628
2629 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2630 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2631 return VOS_STATUS_E_FAILURE;
2632 }
2633 else {
2634 if(*pBufSize != pHddCtx->fw->size) {
2635 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2636 "file size", __func__);
2637 release_firmware(pHddCtx->fw);
2638 pHddCtx->fw = NULL;
2639 return VOS_STATUS_E_FAILURE;
2640 }
2641 else {
2642 if(pBuffer) {
2643 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2644 }
2645 release_firmware(pHddCtx->fw);
2646 pHddCtx->fw = NULL;
2647 }
2648 }
2649
2650 EXIT();
2651
2652 return VOS_STATUS_SUCCESS;
2653}
2654
2655/**---------------------------------------------------------------------------
2656
Jeff Johnson295189b2012-06-20 16:38:30 -07002657 \brief hdd_set_mac_address() -
2658
2659 This function sets the user specified mac address using
2660 the command ifconfig wlanX hw ether <mac adress>.
2661
2662 \param - dev - Pointer to the net device.
2663 - addr - Pointer to the sockaddr.
2664 \return - 0 for success, non zero for failure
2665
2666 --------------------------------------------------------------------------*/
2667
2668static int hdd_set_mac_address(struct net_device *dev, void *addr)
2669{
2670 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2671 struct sockaddr *psta_mac_addr = addr;
2672 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2673
2674 ENTER();
2675
2676 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2677
2678#ifdef HDD_SESSIONIZE
2679 // set the MAC address though the STA ID CFG.
2680 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2681 (v_U8_t *)&pAdapter->macAddressCurrent,
2682 sizeof( pAdapter->macAddressCurrent ),
2683 hdd_set_mac_addr_cb, VOS_FALSE );
2684#endif
2685
2686 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2687
2688 EXIT();
2689 return halStatus;
2690}
2691
2692tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2693{
2694 int i;
2695 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2696 {
2697 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2698 break;
2699 }
2700
2701 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2702 return NULL;
2703
2704 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2705 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2706}
2707
2708void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
2709{
2710 int i;
2711 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2712 {
2713 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
2714 {
2715 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
2716 break;
2717 }
2718 }
2719 return;
2720}
2721
2722#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2723 static struct net_device_ops wlan_drv_ops = {
2724 .ndo_open = hdd_open,
2725 .ndo_stop = hdd_stop,
2726 .ndo_uninit = hdd_uninit,
2727 .ndo_start_xmit = hdd_hard_start_xmit,
2728 .ndo_tx_timeout = hdd_tx_timeout,
2729 .ndo_get_stats = hdd_stats,
2730 .ndo_do_ioctl = hdd_ioctl,
2731 .ndo_set_mac_address = hdd_set_mac_address,
2732 .ndo_select_queue = hdd_select_queue,
2733#ifdef WLAN_FEATURE_PACKET_FILTERING
2734#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
2735 .ndo_set_rx_mode = hdd_set_multicast_list,
2736#else
2737 .ndo_set_multicast_list = hdd_set_multicast_list,
2738#endif //LINUX_VERSION_CODE
2739#endif
2740 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002741 static struct net_device_ops wlan_mon_drv_ops = {
2742 .ndo_open = hdd_mon_open,
2743 .ndo_stop = hdd_stop,
2744 .ndo_uninit = hdd_uninit,
2745 .ndo_start_xmit = hdd_mon_hard_start_xmit,
2746 .ndo_tx_timeout = hdd_tx_timeout,
2747 .ndo_get_stats = hdd_stats,
2748 .ndo_do_ioctl = hdd_ioctl,
2749 .ndo_set_mac_address = hdd_set_mac_address,
2750 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002751
2752#endif
2753
2754void hdd_set_station_ops( struct net_device *pWlanDev )
2755{
2756#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2757 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
2758 pWlanDev->netdev_ops = &wlan_drv_ops;
2759#else
2760 pWlanDev->open = hdd_open;
2761 pWlanDev->stop = hdd_stop;
2762 pWlanDev->uninit = hdd_uninit;
2763 pWlanDev->hard_start_xmit = NULL;
2764 pWlanDev->tx_timeout = hdd_tx_timeout;
2765 pWlanDev->get_stats = hdd_stats;
2766 pWlanDev->do_ioctl = hdd_ioctl;
2767 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
2768 pWlanDev->set_mac_address = hdd_set_mac_address;
2769#endif
2770}
2771
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002772static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07002773{
2774 struct net_device *pWlanDev = NULL;
2775 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002776 /*
2777 * cfg80211 initialization and registration....
2778 */
2779 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
2780
Jeff Johnson295189b2012-06-20 16:38:30 -07002781 if(pWlanDev != NULL)
2782 {
2783
2784 //Save the pointer to the net_device in the HDD adapter
2785 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
2786
Jeff Johnson295189b2012-06-20 16:38:30 -07002787 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
2788
2789 pAdapter->dev = pWlanDev;
2790 pAdapter->pHddCtx = pHddCtx;
2791 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
2792
2793 init_completion(&pAdapter->session_open_comp_var);
2794 init_completion(&pAdapter->session_close_comp_var);
2795 init_completion(&pAdapter->disconnect_comp_var);
2796 init_completion(&pAdapter->linkup_event_var);
2797 init_completion(&pAdapter->cancel_rem_on_chan_var);
2798 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07002799#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2800 init_completion(&pAdapter->offchannel_tx_event);
2801#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002802 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002803#ifdef FEATURE_WLAN_TDLS
2804 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002805 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002806 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002807#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002808 init_completion(&pHddCtx->mc_sus_event_var);
2809 init_completion(&pHddCtx->tx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07002810 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07002811
Jeff Johnson295189b2012-06-20 16:38:30 -07002812 pAdapter->isLinkUpSvcNeeded = FALSE;
2813 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
2814 //Init the net_device structure
2815 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2816
2817 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
2818 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
2819 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
2820 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
2821
2822 hdd_set_station_ops( pAdapter->dev );
2823
2824 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002825 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
2826 pAdapter->wdev.wiphy = pHddCtx->wiphy;
2827 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002828 /* set pWlanDev's parent to underlying device */
2829 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
2830 }
2831
2832 return pAdapter;
2833}
2834
2835VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
2836{
2837 struct net_device *pWlanDev = pAdapter->dev;
2838 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2839 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2840 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2841
2842 if( rtnl_lock_held )
2843 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08002844 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07002845 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
2846 {
2847 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
2848 return VOS_STATUS_E_FAILURE;
2849 }
2850 }
2851 if (register_netdevice(pWlanDev))
2852 {
2853 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
2854 return VOS_STATUS_E_FAILURE;
2855 }
2856 }
2857 else
2858 {
2859 if(register_netdev(pWlanDev))
2860 {
2861 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
2862 return VOS_STATUS_E_FAILURE;
2863 }
2864 }
2865 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
2866
2867 return VOS_STATUS_SUCCESS;
2868}
2869
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002870static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07002871{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002872 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07002873
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002874 if (NULL == pAdapter)
2875 {
2876 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
2877 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07002878 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002879
2880 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2881 {
2882 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
2883 return eHAL_STATUS_NOT_INITIALIZED;
2884 }
2885
2886 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
2887
2888 /* need to make sure all of our scheduled work has completed.
2889 * This callback is called from MC thread context, so it is safe to
2890 * to call below flush workqueue API from here.
2891 */
2892 flush_scheduled_work();
2893
2894 /* We can be blocked while waiting for scheduled work to be
2895 * flushed, and the adapter structure can potentially be freed, in
2896 * which case the magic will have been reset. So make sure the
2897 * magic is still good, and hence the adapter structure is still
2898 * valid, before signaling completion */
2899 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
2900 {
2901 complete(&pAdapter->session_close_comp_var);
2902 }
2903
Jeff Johnson295189b2012-06-20 16:38:30 -07002904 return eHAL_STATUS_SUCCESS;
2905}
2906
2907VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
2908{
2909 struct net_device *pWlanDev = pAdapter->dev;
2910 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2911 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2912 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2913 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2914 int rc = 0;
2915
2916 INIT_COMPLETION(pAdapter->session_open_comp_var);
2917 //Open a SME session for future operation
2918 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
2919 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
2920 if ( !HAL_STATUS_SUCCESS( halStatus ) )
2921 {
2922 hddLog(VOS_TRACE_LEVEL_FATAL,
2923 "sme_OpenSession() failed with status code %08d [x%08lx]",
2924 halStatus, halStatus );
2925 status = VOS_STATUS_E_FAILURE;
2926 goto error_sme_open;
2927 }
2928
2929 //Block on a completion variable. Can't wait forever though.
2930 rc = wait_for_completion_interruptible_timeout(
2931 &pAdapter->session_open_comp_var,
2932 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2933 if (!rc)
2934 {
2935 hddLog(VOS_TRACE_LEVEL_FATAL,
2936 "Session is not opened within timeout period code %08d", rc );
2937 status = VOS_STATUS_E_FAILURE;
2938 goto error_sme_open;
2939 }
2940
2941 // Register wireless extensions
2942 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
2943 {
2944 hddLog(VOS_TRACE_LEVEL_FATAL,
2945 "hdd_register_wext() failed with status code %08d [x%08lx]",
2946 halStatus, halStatus );
2947 status = VOS_STATUS_E_FAILURE;
2948 goto error_register_wext;
2949 }
2950 //Safe to register the hard_start_xmit function again
2951#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2952 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
2953#else
2954 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
2955#endif
2956
2957 //Set the Connection State to Not Connected
2958 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2959
2960 //Set the default operation channel
2961 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
2962
2963 /* Make the default Auth Type as OPEN*/
2964 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2965
2966 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
2967 {
2968 hddLog(VOS_TRACE_LEVEL_FATAL,
2969 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
2970 status, status );
2971 goto error_init_txrx;
2972 }
2973
2974 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2975
2976 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
2977 {
2978 hddLog(VOS_TRACE_LEVEL_FATAL,
2979 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
2980 status, status );
2981 goto error_wmm_init;
2982 }
2983
2984 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2985
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002986#ifdef FEATURE_WLAN_TDLS
2987 if(0 != wlan_hdd_tdls_init(pAdapter))
2988 {
2989 status = VOS_STATUS_E_FAILURE;
2990 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
2991 goto error_tdls_init;
2992 }
2993 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2994#endif
2995
Jeff Johnson295189b2012-06-20 16:38:30 -07002996 return VOS_STATUS_SUCCESS;
2997
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002998#ifdef FEATURE_WLAN_TDLS
2999error_tdls_init:
3000 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3001 hdd_wmm_adapter_close(pAdapter);
3002#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003003error_wmm_init:
3004 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3005 hdd_deinit_tx_rx(pAdapter);
3006error_init_txrx:
3007 hdd_UnregisterWext(pWlanDev);
3008error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003009 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07003010 {
3011 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003012 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07003013 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003014 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07003015 {
3016 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003017 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003018 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003019 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07003020 }
3021}
3022error_sme_open:
3023 return status;
3024}
3025
Jeff Johnson295189b2012-06-20 16:38:30 -07003026void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3027{
3028 hdd_cfg80211_state_t *cfgState;
3029
3030 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
3031
3032 if( NULL != cfgState->buf )
3033 {
3034 int rc;
3035 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
3036 rc = wait_for_completion_interruptible_timeout(
3037 &pAdapter->tx_action_cnf_event,
3038 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3039 if(!rc)
3040 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08003041 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003042 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
3043 }
3044 }
3045 return;
3046}
Jeff Johnson295189b2012-06-20 16:38:30 -07003047
3048void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3049{
3050 ENTER();
3051 switch ( pAdapter->device_mode )
3052 {
3053 case WLAN_HDD_INFRA_STATION:
3054 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003055 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003056 {
3057 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3058 {
3059 hdd_deinit_tx_rx( pAdapter );
3060 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3061 }
3062
3063 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
3064 {
3065 hdd_wmm_adapter_close( pAdapter );
3066 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
3067 }
3068
Jeff Johnson295189b2012-06-20 16:38:30 -07003069 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08003070#ifdef FEATURE_WLAN_TDLS
3071 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
3072 {
3073 wlan_hdd_tdls_exit(pAdapter);
3074 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
3075 }
3076#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003077
3078 break;
3079 }
3080
3081 case WLAN_HDD_SOFTAP:
3082 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003083 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003084 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003085
3086 hdd_unregister_hostapd(pAdapter);
3087 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07003088 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07003089 break;
3090 }
3091
3092 case WLAN_HDD_MONITOR:
3093 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003094 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07003095 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
3096 {
3097 hdd_deinit_tx_rx( pAdapter );
3098 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3099 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003100 if(NULL != pAdapterforTx)
3101 {
3102 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
3103 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003104 break;
3105 }
3106
3107
3108 default:
3109 break;
3110 }
3111
3112 EXIT();
3113}
3114
3115void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
3116{
3117 struct net_device *pWlanDev = pAdapter->dev;
3118
3119 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
3120 if( rtnl_held )
3121 {
3122 unregister_netdevice(pWlanDev);
3123 }
3124 else
3125 {
3126 unregister_netdev(pWlanDev);
3127 }
3128 // note that the pAdapter is no longer valid at this point
3129 // since the memory has been reclaimed
3130 }
3131
3132}
3133
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003134void hdd_set_pwrparams(hdd_context_t *pHddCtx)
3135{
3136 tSirSetPowerParamsReq powerRequest = { 0 };
3137
3138 powerRequest.uIgnoreDTIM = 1;
Yue Mac24062f2013-05-13 17:01:29 -07003139 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003140
3141 if (pHddCtx->cfg_ini->enableModulatedDTIM)
3142 {
3143 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
3144 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
3145 }
3146 else
3147 {
3148 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
3149 }
3150
3151 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
3152 *specified during Enter/Exit BMPS when LCD off*/
3153 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3154 NULL, eANI_BOOLEAN_FALSE);
3155 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3156 NULL, eANI_BOOLEAN_FALSE);
3157
3158 /* switch to the DTIM specified in cfg.ini */
3159 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3160 "Switch to DTIM%d", powerRequest.uListenInterval);
3161 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3162
3163}
3164
3165void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
3166{
3167 /*Switch back to DTIM 1*/
3168 tSirSetPowerParamsReq powerRequest = { 0 };
3169
3170 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
3171 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07003172 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08003173
3174 /* Update ignoreDTIM and ListedInterval in CFG with default values */
3175 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
3176 NULL, eANI_BOOLEAN_FALSE);
3177 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
3178 NULL, eANI_BOOLEAN_FALSE);
3179
3180 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3181 "Switch to DTIM%d",powerRequest.uListenInterval);
3182 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3183
3184}
3185
Jeff Johnson295189b2012-06-20 16:38:30 -07003186VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3187{
3188 VOS_STATUS status = VOS_STATUS_SUCCESS;
3189
3190 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3191 {
3192 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3193 }
3194
3195 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3196 {
3197 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3198 }
3199
3200 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3201 {
3202 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3203 }
3204
3205 return status;
3206}
3207
3208VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3209{
3210 hdd_adapter_t *pAdapter = NULL;
3211 eHalStatus halStatus;
3212 VOS_STATUS status = VOS_STATUS_E_INVAL;
3213 v_BOOL_t disableBmps = FALSE;
3214 v_BOOL_t disableImps = FALSE;
3215
3216 switch(session_type)
3217 {
3218 case WLAN_HDD_INFRA_STATION:
3219 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003220 case WLAN_HDD_P2P_CLIENT:
3221 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003222 //Exit BMPS -> Is Sta/P2P Client is already connected
3223 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3224 if((NULL != pAdapter)&&
3225 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3226 {
3227 disableBmps = TRUE;
3228 }
3229
3230 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3231 if((NULL != pAdapter)&&
3232 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3233 {
3234 disableBmps = TRUE;
3235 }
3236
3237 //Exit both Bmps and Imps incase of Go/SAP Mode
3238 if((WLAN_HDD_SOFTAP == session_type) ||
3239 (WLAN_HDD_P2P_GO == session_type))
3240 {
3241 disableBmps = TRUE;
3242 disableImps = TRUE;
3243 }
3244
3245 if(TRUE == disableImps)
3246 {
3247 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3248 {
3249 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3250 }
3251 }
3252
3253 if(TRUE == disableBmps)
3254 {
3255 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3256 {
3257 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3258
3259 if(eHAL_STATUS_SUCCESS != halStatus)
3260 {
3261 status = VOS_STATUS_E_FAILURE;
3262 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3263 VOS_ASSERT(0);
3264 return status;
3265 }
3266 }
3267
3268 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3269 {
3270 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3271
3272 if(eHAL_STATUS_SUCCESS != halStatus)
3273 {
3274 status = VOS_STATUS_E_FAILURE;
3275 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3276 VOS_ASSERT(0);
3277 return status;
3278 }
3279 }
3280 }
3281
3282 if((TRUE == disableBmps) ||
3283 (TRUE == disableImps))
3284 {
3285 /* Now, get the chip into Full Power now */
3286 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3287 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3288 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3289
3290 if(halStatus != eHAL_STATUS_SUCCESS)
3291 {
3292 if(halStatus == eHAL_STATUS_PMC_PENDING)
3293 {
3294 //Block on a completion variable. Can't wait forever though
3295 wait_for_completion_interruptible_timeout(
3296 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3297 }
3298 else
3299 {
3300 status = VOS_STATUS_E_FAILURE;
3301 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3302 VOS_ASSERT(0);
3303 return status;
3304 }
3305 }
3306
3307 status = VOS_STATUS_SUCCESS;
3308 }
3309
3310 break;
3311 }
3312 return status;
3313}
3314
3315hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003316 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003317 tANI_U8 rtnl_held )
3318{
3319 hdd_adapter_t *pAdapter = NULL;
3320 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3321 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3322 VOS_STATUS exitbmpsStatus;
3323
3324 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3325
3326 //Disable BMPS incase of Concurrency
3327 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3328
3329 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3330 {
3331 //Fail to Exit BMPS
3332 VOS_ASSERT(0);
3333 return NULL;
3334 }
3335
3336 switch(session_type)
3337 {
3338 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003339 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003340 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003341 {
3342 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3343
3344 if( NULL == pAdapter )
3345 return NULL;
3346
Jeff Johnsone7245742012-09-05 17:12:55 -07003347 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3348 NL80211_IFTYPE_P2P_CLIENT:
3349 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003350
Jeff Johnson295189b2012-06-20 16:38:30 -07003351 pAdapter->device_mode = session_type;
3352
3353 status = hdd_init_station_mode( pAdapter );
3354 if( VOS_STATUS_SUCCESS != status )
3355 goto err_free_netdev;
3356
3357 status = hdd_register_interface( pAdapter, rtnl_held );
3358 if( VOS_STATUS_SUCCESS != status )
3359 {
3360 hdd_deinit_adapter(pHddCtx, pAdapter);
3361 goto err_free_netdev;
3362 }
3363 //Stop the Interface TX queue.
3364 netif_tx_disable(pAdapter->dev);
3365 //netif_tx_disable(pWlanDev);
3366 netif_carrier_off(pAdapter->dev);
3367
3368 break;
3369 }
3370
Jeff Johnson295189b2012-06-20 16:38:30 -07003371 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003372 case WLAN_HDD_SOFTAP:
3373 {
3374 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3375 if( NULL == pAdapter )
3376 return NULL;
3377
Jeff Johnson295189b2012-06-20 16:38:30 -07003378 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3379 NL80211_IFTYPE_AP:
3380 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003381 pAdapter->device_mode = session_type;
3382
3383 status = hdd_init_ap_mode(pAdapter);
3384 if( VOS_STATUS_SUCCESS != status )
3385 goto err_free_netdev;
3386
3387 status = hdd_register_hostapd( pAdapter, rtnl_held );
3388 if( VOS_STATUS_SUCCESS != status )
3389 {
3390 hdd_deinit_adapter(pHddCtx, pAdapter);
3391 goto err_free_netdev;
3392 }
3393
3394 netif_tx_disable(pAdapter->dev);
3395 netif_carrier_off(pAdapter->dev);
3396
3397 hdd_set_conparam( 1 );
3398 break;
3399 }
3400 case WLAN_HDD_MONITOR:
3401 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003402 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3403 if( NULL == pAdapter )
3404 return NULL;
3405
3406 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3407 pAdapter->device_mode = session_type;
3408 status = hdd_register_interface( pAdapter, rtnl_held );
3409#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3410 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3411#else
3412 pAdapter->dev->open = hdd_mon_open;
3413 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3414#endif
3415 hdd_init_tx_rx( pAdapter );
3416 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3417 //Set adapter to be used for data tx. It will use either GO or softap.
3418 pAdapter->sessionCtx.monitor.pAdapterForTx =
3419 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003420 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3421 {
3422 pAdapter->sessionCtx.monitor.pAdapterForTx =
3423 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3424 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003425 /* This workqueue will be used to transmit management packet over
3426 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003427 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3428 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3429 return NULL;
3430 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003431
Jeff Johnson295189b2012-06-20 16:38:30 -07003432 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3433 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003434 }
3435 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003436 case WLAN_HDD_FTM:
3437 {
3438 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3439
3440 if( NULL == pAdapter )
3441 return NULL;
3442 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3443 * message while loading driver in FTM mode. */
3444 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3445 pAdapter->device_mode = session_type;
3446 status = hdd_register_interface( pAdapter, rtnl_held );
3447 }
3448 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003449 default:
3450 {
3451 VOS_ASSERT(0);
3452 return NULL;
3453 }
3454 }
3455
3456
3457 if( VOS_STATUS_SUCCESS == status )
3458 {
3459 //Add it to the hdd's session list.
3460 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3461 if( NULL == pHddAdapterNode )
3462 {
3463 status = VOS_STATUS_E_NOMEM;
3464 }
3465 else
3466 {
3467 pHddAdapterNode->pAdapter = pAdapter;
3468 status = hdd_add_adapter_back ( pHddCtx,
3469 pHddAdapterNode );
3470 }
3471 }
3472
3473 if( VOS_STATUS_SUCCESS != status )
3474 {
3475 if( NULL != pAdapter )
3476 {
3477 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3478 pAdapter = NULL;
3479 }
3480 if( NULL != pHddAdapterNode )
3481 {
3482 vos_mem_free( pHddAdapterNode );
3483 }
3484
3485 goto resume_bmps;
3486 }
3487
3488 if(VOS_STATUS_SUCCESS == status)
3489 {
3490 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3491
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003492 //Initialize the WoWL service
3493 if(!hdd_init_wowl(pAdapter))
3494 {
3495 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3496 goto err_free_netdev;
3497 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003498 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003499 return pAdapter;
3500
3501err_free_netdev:
3502 free_netdev(pAdapter->dev);
3503 wlan_hdd_release_intf_addr( pHddCtx,
3504 pAdapter->macAddressCurrent.bytes );
3505
3506resume_bmps:
3507 //If bmps disabled enable it
3508 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3509 {
3510 hdd_enable_bmps_imps(pHddCtx);
3511 }
3512 return NULL;
3513}
3514
3515VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3516 tANI_U8 rtnl_held )
3517{
3518 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3519 VOS_STATUS status;
3520
3521 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3522 if( VOS_STATUS_SUCCESS != status )
3523 return status;
3524
3525 while ( pCurrent->pAdapter != pAdapter )
3526 {
3527 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3528 if( VOS_STATUS_SUCCESS != status )
3529 break;
3530
3531 pCurrent = pNext;
3532 }
3533 pAdapterNode = pCurrent;
3534 if( VOS_STATUS_SUCCESS == status )
3535 {
3536 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3537 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3538 hdd_remove_adapter( pHddCtx, pAdapterNode );
3539 vos_mem_free( pAdapterNode );
3540
Jeff Johnson295189b2012-06-20 16:38:30 -07003541
3542 /* If there is a single session of STA/P2P client, re-enable BMPS */
3543 if ((!vos_concurrent_sessions_running()) &&
3544 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3545 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3546 {
3547 hdd_enable_bmps_imps(pHddCtx);
3548 }
3549
3550 return VOS_STATUS_SUCCESS;
3551 }
3552
3553 return VOS_STATUS_E_FAILURE;
3554}
3555
3556VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3557{
3558 hdd_adapter_list_node_t *pHddAdapterNode;
3559 VOS_STATUS status;
3560
3561 ENTER();
3562
3563 do
3564 {
3565 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3566 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3567 {
3568 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3569 vos_mem_free( pHddAdapterNode );
3570 }
3571 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3572
3573 EXIT();
3574
3575 return VOS_STATUS_SUCCESS;
3576}
3577
3578void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3579{
3580 v_U8_t addIE[1] = {0};
3581
3582 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3583 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3584 eANI_BOOLEAN_FALSE) )
3585 {
3586 hddLog(LOGE,
3587 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3588 }
3589
3590 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3591 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3592 eANI_BOOLEAN_FALSE) )
3593 {
3594 hddLog(LOGE,
3595 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3596 }
3597
3598 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3599 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3600 eANI_BOOLEAN_FALSE) )
3601 {
3602 hddLog(LOGE,
3603 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3604 }
3605}
3606
3607VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3608{
3609 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3610 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3611 union iwreq_data wrqu;
3612
3613 ENTER();
3614
3615 switch(pAdapter->device_mode)
3616 {
3617 case WLAN_HDD_INFRA_STATION:
3618 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003619 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003620 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3621 {
3622 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3623 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3624 pAdapter->sessionId,
3625 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3626 else
3627 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3628 pAdapter->sessionId,
3629 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3630 //success implies disconnect command got queued up successfully
3631 if(halStatus == eHAL_STATUS_SUCCESS)
3632 {
3633 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3634 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3635 }
3636 memset(&wrqu, '\0', sizeof(wrqu));
3637 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3638 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3639 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3640 }
3641 else
3642 {
3643 hdd_abort_mac_scan(pHddCtx);
3644 }
3645
3646 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3647 {
3648 INIT_COMPLETION(pAdapter->session_close_comp_var);
3649 if (eHAL_STATUS_SUCCESS ==
3650 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3651 hdd_smeCloseSessionCallback, pAdapter))
3652 {
3653 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003654 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003655 &pAdapter->session_close_comp_var,
3656 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3657 }
3658 }
3659
3660 break;
3661
3662 case WLAN_HDD_SOFTAP:
3663 case WLAN_HDD_P2P_GO:
3664 //Any softap specific cleanup here...
3665 mutex_lock(&pHddCtx->sap_lock);
3666 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3667 {
3668 VOS_STATUS status;
3669 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3670
3671 //Stop Bss.
3672 status = WLANSAP_StopBss(pHddCtx->pvosContext);
3673 if (VOS_IS_STATUS_SUCCESS(status))
3674 {
3675 hdd_hostapd_state_t *pHostapdState =
3676 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3677
3678 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
3679
3680 if (!VOS_IS_STATUS_SUCCESS(status))
3681 {
3682 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003683 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003684 }
3685 }
3686 else
3687 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003688 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003689 }
3690 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
3691
3692 if (eHAL_STATUS_FAILURE ==
3693 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
3694 0, NULL, eANI_BOOLEAN_FALSE))
3695 {
3696 hddLog(LOGE,
3697 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003698 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003699 }
3700
3701 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
3702 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
3703 eANI_BOOLEAN_FALSE) )
3704 {
3705 hddLog(LOGE,
3706 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
3707 }
3708
3709 // Reset WNI_CFG_PROBE_RSP Flags
3710 wlan_hdd_reset_prob_rspies(pAdapter);
3711 kfree(pAdapter->sessionCtx.ap.beacon);
3712 pAdapter->sessionCtx.ap.beacon = NULL;
3713 }
3714 mutex_unlock(&pHddCtx->sap_lock);
3715 break;
3716 case WLAN_HDD_MONITOR:
3717 break;
3718 default:
3719 break;
3720 }
3721
3722 EXIT();
3723 return VOS_STATUS_SUCCESS;
3724}
3725
3726VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
3727{
3728 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3729 VOS_STATUS status;
3730 hdd_adapter_t *pAdapter;
3731
3732 ENTER();
3733
3734 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3735
3736 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3737 {
3738 pAdapter = pAdapterNode->pAdapter;
3739 netif_tx_disable(pAdapter->dev);
3740 netif_carrier_off(pAdapter->dev);
3741
3742 hdd_stop_adapter( pHddCtx, pAdapter );
3743
3744 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3745 pAdapterNode = pNext;
3746 }
3747
3748 EXIT();
3749
3750 return VOS_STATUS_SUCCESS;
3751}
3752
3753VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
3754{
3755 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3756 VOS_STATUS status;
3757 hdd_adapter_t *pAdapter;
3758
3759 ENTER();
3760
3761 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3762
3763 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3764 {
3765 pAdapter = pAdapterNode->pAdapter;
3766 netif_tx_disable(pAdapter->dev);
3767 netif_carrier_off(pAdapter->dev);
3768
3769 //Record whether STA is associated
3770 pAdapter->sessionCtx.station.bSendDisconnect =
3771 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
3772 VOS_TRUE : VOS_FALSE;
3773
3774 hdd_deinit_tx_rx(pAdapter);
3775 hdd_wmm_adapter_close(pAdapter);
3776
3777 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3778 pAdapterNode = pNext;
3779 }
3780
3781 EXIT();
3782
3783 return VOS_STATUS_SUCCESS;
3784}
3785
3786VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
3787{
3788 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3789 VOS_STATUS status;
3790 hdd_adapter_t *pAdapter;
3791 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
3792
3793 ENTER();
3794
3795 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3796
3797 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3798 {
3799 pAdapter = pAdapterNode->pAdapter;
3800
3801 switch(pAdapter->device_mode)
3802 {
3803 case WLAN_HDD_INFRA_STATION:
3804 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003805 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003806 hdd_init_station_mode(pAdapter);
3807 /* Open the gates for HDD to receive Wext commands */
3808 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003809 pHddCtx->scan_info.mScanPending = FALSE;
3810 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003811
3812 //Trigger the initial scan
3813 hdd_wlan_initial_scan(pAdapter);
3814
3815 //Indicate disconnect event to supplicant if associated previously
3816 if(pAdapter->sessionCtx.station.bSendDisconnect)
3817 {
3818 union iwreq_data wrqu;
3819 memset(&wrqu, '\0', sizeof(wrqu));
3820 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3821 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3822 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3823 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
3824
Jeff Johnson295189b2012-06-20 16:38:30 -07003825 /* indicate disconnected event to nl80211 */
3826 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
3827 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003828 }
3829 break;
3830
3831 case WLAN_HDD_SOFTAP:
3832 /* softAP can handle SSR */
3833 break;
3834
3835 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003836 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
3837 __func__);
3838 /* event supplicant to restart */
3839 cfg80211_del_sta(pAdapter->dev,
3840 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003841 break;
3842
3843 case WLAN_HDD_MONITOR:
3844 /* monitor interface start */
3845 break;
3846 default:
3847 break;
3848 }
3849
3850 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3851 pAdapterNode = pNext;
3852 }
3853
3854 EXIT();
3855
3856 return VOS_STATUS_SUCCESS;
3857}
3858
3859VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
3860{
3861 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3862 hdd_adapter_t *pAdapter;
3863 VOS_STATUS status;
3864 v_U32_t roamId;
3865
3866 ENTER();
3867
3868 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3869
3870 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3871 {
3872 pAdapter = pAdapterNode->pAdapter;
3873
3874 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3875 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
3876 {
3877 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3878 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3879
3880 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3881 init_completion(&pAdapter->disconnect_comp_var);
3882 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
3883 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3884
3885 wait_for_completion_interruptible_timeout(
3886 &pAdapter->disconnect_comp_var,
3887 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3888
3889 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
3890 pHddCtx->isAmpAllowed = VOS_FALSE;
3891 sme_RoamConnect(pHddCtx->hHal,
3892 pAdapter->sessionId, &(pWextState->roamProfile),
3893 &roamId);
3894 }
3895
3896 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3897 pAdapterNode = pNext;
3898 }
3899
3900 EXIT();
3901
3902 return VOS_STATUS_SUCCESS;
3903}
3904
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07003905void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
3906{
3907 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3908 VOS_STATUS status;
3909 hdd_adapter_t *pAdapter;
3910 hdd_station_ctx_t *pHddStaCtx;
3911 hdd_ap_ctx_t *pHddApCtx;
3912 hdd_hostapd_state_t * pHostapdState;
3913 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
3914 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
3915 const char *p2pMode = "DEV";
3916 const char *ccMode = "Standalone";
3917 int n;
3918
3919 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3920 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3921 {
3922 pAdapter = pAdapterNode->pAdapter;
3923 switch (pAdapter->device_mode) {
3924 case WLAN_HDD_INFRA_STATION:
3925 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3926 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3927 staChannel = pHddStaCtx->conn_info.operationChannel;
3928 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
3929 }
3930 break;
3931 case WLAN_HDD_P2P_CLIENT:
3932 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3933 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3934 p2pChannel = pHddStaCtx->conn_info.operationChannel;
3935 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
3936 p2pMode = "CLI";
3937 }
3938 break;
3939 case WLAN_HDD_P2P_GO:
3940 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3941 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3942 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3943 p2pChannel = pHddApCtx->operatingChannel;
3944 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
3945 }
3946 p2pMode = "GO";
3947 break;
3948 case WLAN_HDD_SOFTAP:
3949 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3950 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3951 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3952 apChannel = pHddApCtx->operatingChannel;
3953 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
3954 }
3955 break;
3956 default:
3957 break;
3958 }
3959 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3960 pAdapterNode = pNext;
3961 }
3962 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
3963 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
3964 }
3965 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
3966 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
3967 if (p2pChannel > 0) {
3968 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
3969 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
3970 }
3971 if (apChannel > 0) {
3972 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
3973 apChannel, MAC_ADDR_ARRAY(apBssid));
3974 }
3975
3976 if (p2pChannel > 0 && apChannel > 0) {
3977 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
3978 }
3979}
3980
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003981bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07003982{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003983 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07003984}
3985
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003986/* Once SSR is disabled then it cannot be set. */
3987void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07003988{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003989 if (HDD_SSR_DISABLED == isSsrRequired)
3990 return;
3991
Jeff Johnson295189b2012-06-20 16:38:30 -07003992 isSsrRequired = value;
3993}
3994
3995VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
3996 hdd_adapter_list_node_t** ppAdapterNode)
3997{
3998 VOS_STATUS status;
3999 spin_lock(&pHddCtx->hddAdapters.lock);
4000 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
4001 (hdd_list_node_t**) ppAdapterNode );
4002 spin_unlock(&pHddCtx->hddAdapters.lock);
4003 return status;
4004}
4005
4006VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
4007 hdd_adapter_list_node_t* pAdapterNode,
4008 hdd_adapter_list_node_t** pNextAdapterNode)
4009{
4010 VOS_STATUS status;
4011 spin_lock(&pHddCtx->hddAdapters.lock);
4012 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
4013 (hdd_list_node_t*) pAdapterNode,
4014 (hdd_list_node_t**)pNextAdapterNode );
4015
4016 spin_unlock(&pHddCtx->hddAdapters.lock);
4017 return status;
4018}
4019
4020VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
4021 hdd_adapter_list_node_t* pAdapterNode)
4022{
4023 VOS_STATUS status;
4024 spin_lock(&pHddCtx->hddAdapters.lock);
4025 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
4026 &pAdapterNode->node );
4027 spin_unlock(&pHddCtx->hddAdapters.lock);
4028 return status;
4029}
4030
4031VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
4032 hdd_adapter_list_node_t** ppAdapterNode)
4033{
4034 VOS_STATUS status;
4035 spin_lock(&pHddCtx->hddAdapters.lock);
4036 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
4037 (hdd_list_node_t**) ppAdapterNode );
4038 spin_unlock(&pHddCtx->hddAdapters.lock);
4039 return status;
4040}
4041
4042VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
4043 hdd_adapter_list_node_t* pAdapterNode)
4044{
4045 VOS_STATUS status;
4046 spin_lock(&pHddCtx->hddAdapters.lock);
4047 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
4048 (hdd_list_node_t*) pAdapterNode );
4049 spin_unlock(&pHddCtx->hddAdapters.lock);
4050 return status;
4051}
4052
4053VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
4054 hdd_adapter_list_node_t* pAdapterNode)
4055{
4056 VOS_STATUS status;
4057 spin_lock(&pHddCtx->hddAdapters.lock);
4058 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
4059 (hdd_list_node_t*) pAdapterNode );
4060 spin_unlock(&pHddCtx->hddAdapters.lock);
4061 return status;
4062}
4063
4064hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
4065 tSirMacAddr macAddr )
4066{
4067 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4068 hdd_adapter_t *pAdapter;
4069 VOS_STATUS status;
4070
4071 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4072
4073 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4074 {
4075 pAdapter = pAdapterNode->pAdapter;
4076
4077 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
4078 macAddr, sizeof(tSirMacAddr) ) )
4079 {
4080 return pAdapter;
4081 }
4082 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4083 pAdapterNode = pNext;
4084 }
4085
4086 return NULL;
4087
4088}
4089
4090hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
4091{
4092 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4093 hdd_adapter_t *pAdapter;
4094 VOS_STATUS status;
4095
4096 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4097
4098 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4099 {
4100 pAdapter = pAdapterNode->pAdapter;
4101
4102 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
4103 IFNAMSIZ ) )
4104 {
4105 return pAdapter;
4106 }
4107 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4108 pAdapterNode = pNext;
4109 }
4110
4111 return NULL;
4112
4113}
4114
4115hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
4116{
4117 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4118 hdd_adapter_t *pAdapter;
4119 VOS_STATUS status;
4120
4121 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4122
4123 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4124 {
4125 pAdapter = pAdapterNode->pAdapter;
4126
4127 if( pAdapter && (mode == pAdapter->device_mode) )
4128 {
4129 return pAdapter;
4130 }
4131 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4132 pAdapterNode = pNext;
4133 }
4134
4135 return NULL;
4136
4137}
4138
4139//Remove this function later
4140hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
4141{
4142 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4143 hdd_adapter_t *pAdapter;
4144 VOS_STATUS status;
4145
4146 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4147
4148 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4149 {
4150 pAdapter = pAdapterNode->pAdapter;
4151
4152 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
4153 {
4154 return pAdapter;
4155 }
4156
4157 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4158 pAdapterNode = pNext;
4159 }
4160
4161 return NULL;
4162
4163}
4164
Jeff Johnson295189b2012-06-20 16:38:30 -07004165/**---------------------------------------------------------------------------
4166
4167 \brief hdd_set_monitor_tx_adapter() -
4168
4169 This API initializes the adapter to be used while transmitting on monitor
4170 adapter.
4171
4172 \param - pHddCtx - Pointer to the HDD context.
4173 pAdapter - Adapter that will used for TX. This can be NULL.
4174 \return - None.
4175 --------------------------------------------------------------------------*/
4176void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4177{
4178 hdd_adapter_t *pMonAdapter;
4179
4180 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4181
4182 if( NULL != pMonAdapter )
4183 {
4184 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4185 }
4186}
Jeff Johnson295189b2012-06-20 16:38:30 -07004187/**---------------------------------------------------------------------------
4188
4189 \brief hdd_select_queue() -
4190
4191 This API returns the operating channel of the requested device mode
4192
4193 \param - pHddCtx - Pointer to the HDD context.
4194 - mode - Device mode for which operating channel is required
4195 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4196 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4197 \return - channel number. "0" id the requested device is not found OR it is not connected.
4198 --------------------------------------------------------------------------*/
4199v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4200{
4201 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4202 VOS_STATUS status;
4203 hdd_adapter_t *pAdapter;
4204 v_U8_t operatingChannel = 0;
4205
4206 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4207
4208 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4209 {
4210 pAdapter = pAdapterNode->pAdapter;
4211
4212 if( mode == pAdapter->device_mode )
4213 {
4214 switch(pAdapter->device_mode)
4215 {
4216 case WLAN_HDD_INFRA_STATION:
4217 case WLAN_HDD_P2P_CLIENT:
4218 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4219 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4220 break;
4221 case WLAN_HDD_SOFTAP:
4222 case WLAN_HDD_P2P_GO:
4223 /*softap connection info */
4224 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4225 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4226 break;
4227 default:
4228 break;
4229 }
4230
4231 break; //Found the device of interest. break the loop
4232 }
4233
4234 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4235 pAdapterNode = pNext;
4236 }
4237 return operatingChannel;
4238}
4239
4240#ifdef WLAN_FEATURE_PACKET_FILTERING
4241/**---------------------------------------------------------------------------
4242
4243 \brief hdd_set_multicast_list() -
4244
4245 This used to set the multicast address list.
4246
4247 \param - dev - Pointer to the WLAN device.
4248 - skb - Pointer to OS packet (sk_buff).
4249 \return - success/fail
4250
4251 --------------------------------------------------------------------------*/
4252static void hdd_set_multicast_list(struct net_device *dev)
4253{
4254 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004255 int mc_count;
4256 int i = 0;
4257 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304258
4259 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004260 {
4261 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304262 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004263 return;
4264 }
4265
4266 if (dev->flags & IFF_ALLMULTI)
4267 {
4268 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004269 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304270 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004271 }
4272 else
4273 {
4274 mc_count = netdev_mc_count(dev);
4275 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004276 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004277 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4278 {
4279 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004280 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304281 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004282 return;
4283 }
4284
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304285 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004286
4287 netdev_for_each_mc_addr(ha, dev) {
4288 if (i == mc_count)
4289 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304290 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4291 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4292 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004293 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304294 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004295 i++;
4296 }
4297 }
4298 return;
4299}
4300#endif
4301
4302/**---------------------------------------------------------------------------
4303
4304 \brief hdd_select_queue() -
4305
4306 This function is registered with the Linux OS for network
4307 core to decide which queue to use first.
4308
4309 \param - dev - Pointer to the WLAN device.
4310 - skb - Pointer to OS packet (sk_buff).
4311 \return - ac, Queue Index/access category corresponding to UP in IP header
4312
4313 --------------------------------------------------------------------------*/
4314v_U16_t hdd_select_queue(struct net_device *dev,
4315 struct sk_buff *skb)
4316{
4317 return hdd_wmm_select_queue(dev, skb);
4318}
4319
4320
4321/**---------------------------------------------------------------------------
4322
4323 \brief hdd_wlan_initial_scan() -
4324
4325 This function triggers the initial scan
4326
4327 \param - pAdapter - Pointer to the HDD adapter.
4328
4329 --------------------------------------------------------------------------*/
4330void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4331{
4332 tCsrScanRequest scanReq;
4333 tCsrChannelInfo channelInfo;
4334 eHalStatus halStatus;
4335 unsigned long scanId;
4336 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4337
4338 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4339 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4340 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4341
4342 if(sme_Is11dSupported(pHddCtx->hHal))
4343 {
4344 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4345 if ( HAL_STATUS_SUCCESS( halStatus ) )
4346 {
4347 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4348 if( !scanReq.ChannelInfo.ChannelList )
4349 {
4350 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4351 vos_mem_free(channelInfo.ChannelList);
4352 return;
4353 }
4354 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4355 channelInfo.numOfChannels);
4356 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4357 vos_mem_free(channelInfo.ChannelList);
4358 }
4359
4360 scanReq.scanType = eSIR_PASSIVE_SCAN;
4361 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4362 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4363 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4364 }
4365 else
4366 {
4367 scanReq.scanType = eSIR_ACTIVE_SCAN;
4368 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4369 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4370 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4371 }
4372
4373 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4374 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4375 {
4376 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4377 __func__, halStatus );
4378 }
4379
4380 if(sme_Is11dSupported(pHddCtx->hHal))
4381 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4382}
4383
4384struct fullPowerContext
4385{
4386 struct completion completion;
4387 unsigned int magic;
4388};
4389#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4390
4391/**---------------------------------------------------------------------------
4392
4393 \brief hdd_full_power_callback() - HDD full power callback function
4394
4395 This is the function invoked by SME to inform the result of a full power
4396 request issued by HDD
4397
4398 \param - callbackcontext - Pointer to cookie
4399 \param - status - result of request
4400
4401 \return - None
4402
4403 --------------------------------------------------------------------------*/
4404static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4405{
4406 struct fullPowerContext *pContext = callbackContext;
4407
4408 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304409 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004410
4411 if (NULL == callbackContext)
4412 {
4413 hddLog(VOS_TRACE_LEVEL_ERROR,
4414 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004415 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004416 return;
4417 }
4418
4419 /* there is a race condition that exists between this callback function
4420 and the caller since the caller could time out either before or
4421 while this code is executing. we'll assume the timeout hasn't
4422 occurred, but we'll verify that right before we save our work */
4423
4424 if (POWER_CONTEXT_MAGIC != pContext->magic)
4425 {
4426 /* the caller presumably timed out so there is nothing we can do */
4427 hddLog(VOS_TRACE_LEVEL_WARN,
4428 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004429 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004430 return;
4431 }
4432
4433 /* the race is on. caller could have timed out immediately after
4434 we verified the magic, but if so, caller will wait a short time
4435 for us to notify the caller, so the context will stay valid */
4436 complete(&pContext->completion);
4437}
4438
4439/**---------------------------------------------------------------------------
4440
4441 \brief hdd_wlan_exit() - HDD WLAN exit function
4442
4443 This is the driver exit point (invoked during rmmod)
4444
4445 \param - pHddCtx - Pointer to the HDD Context
4446
4447 \return - None
4448
4449 --------------------------------------------------------------------------*/
4450void hdd_wlan_exit(hdd_context_t *pHddCtx)
4451{
4452 eHalStatus halStatus;
4453 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4454 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304455 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004456 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004457 struct fullPowerContext powerContext;
4458 long lrc;
4459
4460 ENTER();
4461
Jeff Johnson88ba7742013-02-27 14:36:02 -08004462 if (VOS_FTM_MODE != hdd_get_conparam())
4463 {
4464 // Unloading, restart logic is no more required.
4465 wlan_hdd_restart_deinit(pHddCtx);
4466 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004467
Jeff Johnson295189b2012-06-20 16:38:30 -07004468 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004469 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004470 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004471 {
4472 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4473 WLAN_HDD_INFRA_STATION);
4474 if (pAdapter == NULL)
4475 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4476
4477 if (pAdapter != NULL)
4478 {
4479 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4480 hdd_UnregisterWext(pAdapter->dev);
4481 }
4482 }
4483 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004484
Jeff Johnson295189b2012-06-20 16:38:30 -07004485 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004486 {
4487 wlan_hdd_ftm_close(pHddCtx);
4488 goto free_hdd_ctx;
4489 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004490 //Stop the Interface TX queue.
4491 //netif_tx_disable(pWlanDev);
4492 //netif_carrier_off(pWlanDev);
4493
Jeff Johnson295189b2012-06-20 16:38:30 -07004494 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4495 {
4496 pAdapter = hdd_get_adapter(pHddCtx,
4497 WLAN_HDD_SOFTAP);
4498 }
4499 else
4500 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004501 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004502 {
4503 pAdapter = hdd_get_adapter(pHddCtx,
4504 WLAN_HDD_INFRA_STATION);
4505 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004506 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004507 /* DeRegister with platform driver as client for Suspend/Resume */
4508 vosStatus = hddDeregisterPmOps(pHddCtx);
4509 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4510 {
4511 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4512 VOS_ASSERT(0);
4513 }
4514
4515 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4516 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4517 {
4518 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4519 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004520
4521 // Cancel any outstanding scan requests. We are about to close all
4522 // of our adapters, but an adapter structure is what SME passes back
4523 // to our callback function. Hence if there are any outstanding scan
4524 // requests then there is a race condition between when the adapter
4525 // is closed and when the callback is invoked. We try to resolve that
4526 // race condition here by canceling any outstanding scans before we
4527 // close the adapters.
4528 // Note that the scans may be cancelled in an asynchronous manner, so
4529 // ideally there needs to be some kind of synchronization. Rather than
4530 // introduce a new synchronization here, we will utilize the fact that
4531 // we are about to Request Full Power, and since that is synchronized,
4532 // the expectation is that by the time Request Full Power has completed,
4533 // all scans will be cancelled.
4534 hdd_abort_mac_scan( pHddCtx );
4535
4536 //Disable IMPS/BMPS as we do not want the device to enter any power
4537 //save mode during shutdown
4538 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4539 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4540 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4541
4542 //Ensure that device is in full power as we will touch H/W during vos_Stop
4543 init_completion(&powerContext.completion);
4544 powerContext.magic = POWER_CONTEXT_MAGIC;
4545
4546 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4547 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4548
4549 if (eHAL_STATUS_SUCCESS != halStatus)
4550 {
4551 if (eHAL_STATUS_PMC_PENDING == halStatus)
4552 {
4553 /* request was sent -- wait for the response */
4554 lrc = wait_for_completion_interruptible_timeout(
4555 &powerContext.completion,
4556 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4557 /* either we have a response or we timed out
4558 either way, first invalidate our magic */
4559 powerContext.magic = 0;
4560 if (lrc <= 0)
4561 {
4562 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004563 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004564 /* there is a race condition such that the callback
4565 function could be executing at the same time we are. of
4566 primary concern is if the callback function had already
4567 verified the "magic" but hasn't yet set the completion
4568 variable. Since the completion variable is on our
4569 stack, we'll delay just a bit to make sure the data is
4570 still valid if that is the case */
4571 msleep(50);
4572 }
4573 }
4574 else
4575 {
4576 hddLog(VOS_TRACE_LEVEL_ERROR,
4577 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004578 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004579 VOS_ASSERT(0);
4580 /* continue -- need to clean up as much as possible */
4581 }
4582 }
4583
4584 // Unregister the Net Device Notifier
4585 unregister_netdevice_notifier(&hdd_netdev_notifier);
4586
Jeff Johnson295189b2012-06-20 16:38:30 -07004587 hdd_stop_all_adapters( pHddCtx );
4588
Jeff Johnson295189b2012-06-20 16:38:30 -07004589#ifdef WLAN_BTAMP_FEATURE
4590 vosStatus = WLANBAP_Stop(pVosContext);
4591 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4592 {
4593 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4594 "%s: Failed to stop BAP",__func__);
4595 }
4596#endif //WLAN_BTAMP_FEATURE
4597
4598 //Stop all the modules
4599 vosStatus = vos_stop( pVosContext );
4600 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4601 {
4602 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4603 "%s: Failed to stop VOSS",__func__);
4604 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4605 }
4606
Jeff Johnson295189b2012-06-20 16:38:30 -07004607 //Assert Deep sleep signal now to put Libra HW in lowest power state
4608 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4609 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4610
4611 //Vote off any PMIC voltage supplies
4612 vos_chipPowerDown(NULL, NULL, NULL);
4613
4614 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4615
4616 //Clean up HDD Nlink Service
4617 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
4618 nl_srv_exit();
4619
4620 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004621 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004622
4623 //Close the scheduler before calling vos_close to make sure no thread is
4624 // scheduled after the each module close is called i.e after all the data
4625 // structures are freed.
4626 vosStatus = vos_sched_close( pVosContext );
4627 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4628 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4629 "%s: Failed to close VOSS Scheduler",__func__);
4630 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4631 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004632#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004633#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4634 /* Destroy the wake lock */
4635 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4636#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004637 /* Destroy the wake lock */
4638 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004639#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004640
4641 //Close VOSS
4642 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4643 vos_close(pVosContext);
4644
Jeff Johnson295189b2012-06-20 16:38:30 -07004645 //Close Watchdog
4646 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4647 vos_watchdog_close(pVosContext);
4648
4649 /* Cancel the vote for XO Core ON.
4650 * This is done here to ensure there is no race condition since MC, TX and WD threads have
4651 * exited at this point
4652 */
4653 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
4654 " when WLAN is turned OFF\n");
4655 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4656 {
4657 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
4658 " Not returning failure."
4659 " Power consumed will be high\n");
4660 }
4661
4662 hdd_close_all_adapters( pHddCtx );
4663
4664
4665 //Free up dynamically allocated members inside HDD Adapter
4666 kfree(pHddCtx->cfg_ini);
4667 pHddCtx->cfg_ini= NULL;
4668
4669 /* free the power on lock from platform driver */
4670 if (free_riva_power_on_lock("wlan"))
4671 {
4672 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
4673 __func__);
4674 }
4675
Jeff Johnson88ba7742013-02-27 14:36:02 -08004676free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08004677 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004678 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004679 if (hdd_is_ssr_required())
4680 {
4681 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07004682 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07004683 msleep(5000);
4684 }
4685 hdd_set_ssr_required (VOS_FALSE);
4686}
4687
4688
4689/**---------------------------------------------------------------------------
4690
4691 \brief hdd_update_config_from_nv() - Function to update the contents of
4692 the running configuration with parameters taken from NV storage
4693
4694 \param - pHddCtx - Pointer to the HDD global context
4695
4696 \return - VOS_STATUS_SUCCESS if successful
4697
4698 --------------------------------------------------------------------------*/
4699static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
4700{
Jeff Johnson295189b2012-06-20 16:38:30 -07004701 v_BOOL_t itemIsValid = VOS_FALSE;
4702 VOS_STATUS status;
4703 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
4704 v_U8_t macLoop;
4705
4706 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
4707 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
4708 if(status != VOS_STATUS_SUCCESS)
4709 {
4710 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
4711 return VOS_STATUS_E_FAILURE;
4712 }
4713
4714 if (itemIsValid == VOS_TRUE)
4715 {
4716 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
4717 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
4718 VOS_MAX_CONCURRENCY_PERSONA);
4719 if(status != VOS_STATUS_SUCCESS)
4720 {
4721 /* Get MAC from NV fail, not update CFG info
4722 * INI MAC value will be used for MAC setting */
4723 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
4724 return VOS_STATUS_E_FAILURE;
4725 }
4726
4727 /* If first MAC is not valid, treat all others are not valid
4728 * Then all MACs will be got from ini file */
4729 if(vos_is_macaddr_zero(&macFromNV[0]))
4730 {
4731 /* MAC address in NV file is not configured yet */
4732 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
4733 return VOS_STATUS_E_INVAL;
4734 }
4735
4736 /* Get MAC address from NV, update CFG info */
4737 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
4738 {
4739 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
4740 {
4741 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
4742 /* This MAC is not valid, skip it
4743 * This MAC will be got from ini file */
4744 }
4745 else
4746 {
4747 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
4748 (v_U8_t *)&macFromNV[macLoop].bytes[0],
4749 VOS_MAC_ADDR_SIZE);
4750 }
4751 }
4752 }
4753 else
4754 {
4755 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
4756 return VOS_STATUS_E_FAILURE;
4757 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004758
Jeff Johnson295189b2012-06-20 16:38:30 -07004759
4760 return VOS_STATUS_SUCCESS;
4761}
4762
4763/**---------------------------------------------------------------------------
4764
4765 \brief hdd_post_voss_start_config() - HDD post voss start config helper
4766
4767 \param - pAdapter - Pointer to the HDD
4768
4769 \return - None
4770
4771 --------------------------------------------------------------------------*/
4772VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
4773{
4774 eHalStatus halStatus;
4775 v_U32_t listenInterval;
4776
Jeff Johnson295189b2012-06-20 16:38:30 -07004777
4778 // Send ready indication to the HDD. This will kick off the MAC
4779 // into a 'running' state and should kick off an initial scan.
4780 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
4781 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4782 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304783 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07004784 "code %08d [x%08x]",__func__, halStatus, halStatus );
4785 return VOS_STATUS_E_FAILURE;
4786 }
4787
4788 // Set default LI into HDD context,
4789 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
4790 // And RIVA will crash
4791 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
4792 pHddCtx->hdd_actual_LI_value = listenInterval;
4793
4794 return VOS_STATUS_SUCCESS;
4795}
4796
Jeff Johnson295189b2012-06-20 16:38:30 -07004797/* wake lock APIs for HDD */
4798void hdd_prevent_suspend(void)
4799{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004800#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004801 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004802#else
4803 wcnss_prevent_suspend();
4804#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004805}
4806
4807void hdd_allow_suspend(void)
4808{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004809#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004810 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004811#else
4812 wcnss_allow_suspend();
4813#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004814}
4815
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004816void hdd_allow_suspend_timeout(v_U32_t timeout)
4817{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004818#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07004819 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004820#else
4821 /* Do nothing as there is no API in wcnss for timeout*/
4822#endif
4823}
4824
Jeff Johnson295189b2012-06-20 16:38:30 -07004825/**---------------------------------------------------------------------------
4826
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004827 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
4828 information between Host and Riva
4829
4830 This function gets reported version of FW
4831 It also finds the version of Riva headers used to compile the host
4832 It compares the above two and prints a warning if they are different
4833 It gets the SW and HW version string
4834 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
4835 indicating the features they support through a bitmap
4836
4837 \param - pHddCtx - Pointer to HDD context
4838
4839 \return - void
4840
4841 --------------------------------------------------------------------------*/
4842
4843void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
4844{
4845
4846 tSirVersionType versionCompiled;
4847 tSirVersionType versionReported;
4848 tSirVersionString versionString;
4849 tANI_U8 fwFeatCapsMsgSupported = 0;
4850 VOS_STATUS vstatus;
4851
4852 /* retrieve and display WCNSS version information */
4853 do {
4854
4855 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
4856 &versionCompiled);
4857 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4858 {
4859 hddLog(VOS_TRACE_LEVEL_FATAL,
4860 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004861 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004862 break;
4863 }
4864
4865 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
4866 &versionReported);
4867 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4868 {
4869 hddLog(VOS_TRACE_LEVEL_FATAL,
4870 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004871 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004872 break;
4873 }
4874
4875 if ((versionCompiled.major != versionReported.major) ||
4876 (versionCompiled.minor != versionReported.minor) ||
4877 (versionCompiled.version != versionReported.version) ||
4878 (versionCompiled.revision != versionReported.revision))
4879 {
4880 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4881 "Host expected %u.%u.%u.%u\n",
4882 WLAN_MODULE_NAME,
4883 (int)versionReported.major,
4884 (int)versionReported.minor,
4885 (int)versionReported.version,
4886 (int)versionReported.revision,
4887 (int)versionCompiled.major,
4888 (int)versionCompiled.minor,
4889 (int)versionCompiled.version,
4890 (int)versionCompiled.revision);
4891 }
4892 else
4893 {
4894 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4895 WLAN_MODULE_NAME,
4896 (int)versionReported.major,
4897 (int)versionReported.minor,
4898 (int)versionReported.version,
4899 (int)versionReported.revision);
4900 }
4901
4902 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
4903 versionString,
4904 sizeof(versionString));
4905 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4906 {
4907 hddLog(VOS_TRACE_LEVEL_FATAL,
4908 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004909 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004910 break;
4911 }
4912
4913 pr_info("%s: WCNSS software version %s\n",
4914 WLAN_MODULE_NAME, versionString);
4915
4916 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
4917 versionString,
4918 sizeof(versionString));
4919 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4920 {
4921 hddLog(VOS_TRACE_LEVEL_FATAL,
4922 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004923 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004924 break;
4925 }
4926
4927 pr_info("%s: WCNSS hardware version %s\n",
4928 WLAN_MODULE_NAME, versionString);
4929
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004930 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
4931 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004932 send the message only if it the riva is 1.1
4933 minor numbers for different riva branches:
4934 0 -> (1.0)Mainline Build
4935 1 -> (1.1)Mainline Build
4936 2->(1.04) Stability Build
4937 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004938 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004939 ((versionReported.minor>=1) && (versionReported.version>=1)))
4940 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
4941 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004942
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004943 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08004944 {
4945#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4946 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
4947 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
4948#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004949 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08004950 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004951
4952 } while (0);
4953
4954}
4955
4956/**---------------------------------------------------------------------------
4957
Jeff Johnson295189b2012-06-20 16:38:30 -07004958 \brief hdd_wlan_startup() - HDD init function
4959
4960 This is the driver startup code executed once a WLAN device has been detected
4961
4962 \param - dev - Pointer to the underlying device
4963
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004964 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07004965
4966 --------------------------------------------------------------------------*/
4967
4968int hdd_wlan_startup(struct device *dev )
4969{
4970 VOS_STATUS status;
4971 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004972 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004973 hdd_context_t *pHddCtx = NULL;
4974 v_CONTEXT_t pVosContext= NULL;
4975#ifdef WLAN_BTAMP_FEATURE
4976 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
4977 WLANBAP_ConfigType btAmpConfig;
4978 hdd_config_t *pConfig;
4979#endif
4980 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07004981 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004982
4983 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07004984 /*
4985 * cfg80211: wiphy allocation
4986 */
4987 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
4988
4989 if(wiphy == NULL)
4990 {
4991 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004992 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004993 }
4994
4995 pHddCtx = wiphy_priv(wiphy);
4996
Jeff Johnson295189b2012-06-20 16:38:30 -07004997 //Initialize the adapter context to zeros.
4998 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
4999
Jeff Johnson295189b2012-06-20 16:38:30 -07005000 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07005001 hdd_prevent_suspend();
5002 pHddCtx->isLoadUnloadInProgress = TRUE;
5003
5004 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5005
5006 /*Get vos context here bcoz vos_open requires it*/
5007 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5008
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08005009 if(pVosContext == NULL)
5010 {
5011 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
5012 goto err_free_hdd_context;
5013 }
5014
Jeff Johnson295189b2012-06-20 16:38:30 -07005015 //Save the Global VOSS context in adapter context for future.
5016 pHddCtx->pvosContext = pVosContext;
5017
5018 //Save the adapter context in global context for future.
5019 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
5020
Jeff Johnson295189b2012-06-20 16:38:30 -07005021 pHddCtx->parent_dev = dev;
5022
5023 init_completion(&pHddCtx->full_pwr_comp_var);
5024 init_completion(&pHddCtx->standby_comp_var);
5025 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005026 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08005027 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005028
5029 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
5030
5031 // Load all config first as TL config is needed during vos_open
5032 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
5033 if(pHddCtx->cfg_ini == NULL)
5034 {
5035 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
5036 goto err_free_hdd_context;
5037 }
5038
5039 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
5040
5041 // Read and parse the qcom_cfg.ini file
5042 status = hdd_parse_config_ini( pHddCtx );
5043 if ( VOS_STATUS_SUCCESS != status )
5044 {
5045 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
5046 __func__, WLAN_INI_FILE);
5047 goto err_config;
5048 }
5049
Jeff Johnson295189b2012-06-20 16:38:30 -07005050 /*
5051 * cfg80211: Initialization and registration ...
5052 */
5053 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
5054 {
5055 hddLog(VOS_TRACE_LEVEL_FATAL,
5056 "%s: wlan_hdd_cfg80211_register return failure", __func__);
5057 goto err_wiphy_reg;
5058 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005059
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005060 // Update VOS trace levels based upon the cfg.ini
5061 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
5062 pHddCtx->cfg_ini->vosTraceEnableBAP);
5063 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
5064 pHddCtx->cfg_ini->vosTraceEnableTL);
5065 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
5066 pHddCtx->cfg_ini->vosTraceEnableWDI);
5067 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
5068 pHddCtx->cfg_ini->vosTraceEnableHDD);
5069 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
5070 pHddCtx->cfg_ini->vosTraceEnableSME);
5071 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
5072 pHddCtx->cfg_ini->vosTraceEnablePE);
5073 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
5074 pHddCtx->cfg_ini->vosTraceEnableWDA);
5075 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
5076 pHddCtx->cfg_ini->vosTraceEnableSYS);
5077 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
5078 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005079 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
5080 pHddCtx->cfg_ini->vosTraceEnableSAP);
5081 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
5082 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08005083
Jeff Johnson295189b2012-06-20 16:38:30 -07005084 // Update WDI trace levels based upon the cfg.ini
5085 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
5086 pHddCtx->cfg_ini->wdiTraceEnableDAL);
5087 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
5088 pHddCtx->cfg_ini->wdiTraceEnableCTL);
5089 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
5090 pHddCtx->cfg_ini->wdiTraceEnableDAT);
5091 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
5092 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005093
Jeff Johnson88ba7742013-02-27 14:36:02 -08005094 if (VOS_FTM_MODE == hdd_get_conparam())
5095 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005096 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
5097 {
5098 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
5099 goto err_free_hdd_context;
5100 }
5101 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
5102 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08005103 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005104
Jeff Johnson88ba7742013-02-27 14:36:02 -08005105 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07005106 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5107 {
5108 status = vos_watchdog_open(pVosContext,
5109 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
5110
5111 if(!VOS_IS_STATUS_SUCCESS( status ))
5112 {
5113 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005114 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07005115 }
5116 }
5117
5118 pHddCtx->isLogpInProgress = FALSE;
5119 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5120
Jeff Johnson295189b2012-06-20 16:38:30 -07005121 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
5122 if(!VOS_IS_STATUS_SUCCESS(status))
5123 {
5124 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005125 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005126 }
5127
Jeff Johnson295189b2012-06-20 16:38:30 -07005128 status = vos_open( &pVosContext, 0);
5129 if ( !VOS_IS_STATUS_SUCCESS( status ))
5130 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005131 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
5132 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07005133 }
5134
Jeff Johnson295189b2012-06-20 16:38:30 -07005135 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
5136
5137 if ( NULL == pHddCtx->hHal )
5138 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005139 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005140 goto err_vosclose;
5141 }
5142
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005143 status = vos_preStart( pHddCtx->pvosContext );
5144 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5145 {
5146 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
5147 goto err_vosclose;
5148 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005149
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005150 /* Note that the vos_preStart() sequence triggers the cfg download.
5151 The cfg download must occur before we update the SME config
5152 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07005153 status = hdd_set_sme_config( pHddCtx );
5154
5155 if ( VOS_STATUS_SUCCESS != status )
5156 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005157 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
5158 goto err_vosclose;
5159 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005160
5161 //Initialize the WMM module
5162 status = hdd_wmm_init(pHddCtx);
5163 if (!VOS_IS_STATUS_SUCCESS(status))
5164 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005165 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005166 goto err_vosclose;
5167 }
5168
Jeff Johnson295189b2012-06-20 16:38:30 -07005169 /* In the integrated architecture we update the configuration from
5170 the INI file and from NV before vOSS has been started so that
5171 the final contents are available to send down to the cCPU */
5172
5173 // Apply the cfg.ini to cfg.dat
5174 if (FALSE == hdd_update_config_dat(pHddCtx))
5175 {
5176 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
5177 goto err_vosclose;
5178 }
5179
5180 // Apply the NV to cfg.dat
5181 /* Prima Update MAC address only at here */
5182 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5183 {
5184#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5185 /* There was not a valid set of MAC Addresses in NV. See if the
5186 default addresses were modified by the cfg.ini settings. If so,
5187 we'll use them, but if not, we'll autogenerate a set of MAC
5188 addresses based upon the device serial number */
5189
5190 static const v_MACADDR_t default_address =
5191 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5192 unsigned int serialno;
5193 int i;
5194
5195 serialno = wcnss_get_serial_number();
5196 if ((0 != serialno) &&
5197 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5198 sizeof(default_address))))
5199 {
5200 /* cfg.ini has the default address, invoke autogen logic */
5201
5202 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5203 bytes of the serial number that can be used to generate
5204 the other 3 bytes of the MAC address. Mask off all but
5205 the lower 3 bytes (this will also make sure we don't
5206 overflow in the next step) */
5207 serialno &= 0x00FFFFFF;
5208
5209 /* we need a unique address for each session */
5210 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5211
5212 /* autogen all addresses */
5213 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5214 {
5215 /* start with the entire default address */
5216 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5217 /* then replace the lower 3 bytes */
5218 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5219 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5220 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5221
5222 serialno++;
5223 }
5224
5225 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5226 MAC_ADDRESS_STR,
5227 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5228 }
5229 else
5230#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5231 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005232 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005233 "%s: Invalid MAC address in NV, using MAC from ini file "
5234 MAC_ADDRESS_STR, __func__,
5235 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5236 }
5237 }
5238 {
5239 eHalStatus halStatus;
5240 // Set the MAC Address
5241 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5242 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5243 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5244 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5245
5246 if (!HAL_STATUS_SUCCESS( halStatus ))
5247 {
5248 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5249 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005250 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005251 }
5252 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005253
5254 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5255 Note: Firmware image will be read and downloaded inside vos_start API */
5256 status = vos_start( pHddCtx->pvosContext );
5257 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5258 {
5259 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5260 goto err_vosclose;
5261 }
5262
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005263 /* Exchange capability info between Host and FW and also get versioning info from FW */
5264 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005265
5266 status = hdd_post_voss_start_config( pHddCtx );
5267 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5268 {
5269 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5270 __func__);
5271 goto err_vosstop;
5272 }
5273
Jeff Johnson295189b2012-06-20 16:38:30 -07005274 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5275 {
5276 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5277 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5278 }
5279 else
5280 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005281 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5282 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5283 if (pAdapter != NULL)
5284 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305285 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005286 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305287 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5288 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5289 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005290
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305291 /* Generate the P2P Device Address. This consists of the device's
5292 * primary MAC address with the locally administered bit set.
5293 */
5294 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005295 }
5296 else
5297 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305298 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5299 if (p2p_dev_addr != NULL)
5300 {
5301 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5302 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5303 }
5304 else
5305 {
5306 hddLog(VOS_TRACE_LEVEL_FATAL,
5307 "%s: Failed to allocate mac_address for p2p_device",
5308 __func__);
5309 goto err_close_adapter;
5310 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005311 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005312
5313 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5314 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5315 if ( NULL == pP2pAdapter )
5316 {
5317 hddLog(VOS_TRACE_LEVEL_FATAL,
5318 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005319 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005320 goto err_close_adapter;
5321 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005322 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005323 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005324
5325 if( pAdapter == NULL )
5326 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005327 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5328 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005329 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005330
Jeff Johnson295189b2012-06-20 16:38:30 -07005331#ifdef WLAN_BTAMP_FEATURE
5332 vStatus = WLANBAP_Open(pVosContext);
5333 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5334 {
5335 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5336 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005337 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005338 }
5339
5340 vStatus = BSL_Init(pVosContext);
5341 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5342 {
5343 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5344 "%s: Failed to Init BSL",__func__);
5345 goto err_bap_close;
5346 }
5347 vStatus = WLANBAP_Start(pVosContext);
5348 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5349 {
5350 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5351 "%s: Failed to start TL",__func__);
5352 goto err_bap_close;
5353 }
5354
5355 pConfig = pHddCtx->cfg_ini;
5356 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5357 status = WLANBAP_SetConfig(&btAmpConfig);
5358
5359#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005360
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005361#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5362 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5363 {
5364 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5365 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5366 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5367 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5368 }
5369#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005370#ifdef FEATURE_WLAN_SCAN_PNO
5371 /*SME must send channel update configuration to RIVA*/
5372 sme_UpdateChannelConfig(pHddCtx->hHal);
5373#endif
5374
Jeff Johnson295189b2012-06-20 16:38:30 -07005375 /* Register with platform driver as client for Suspend/Resume */
5376 status = hddRegisterPmOps(pHddCtx);
5377 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5378 {
5379 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5380#ifdef WLAN_BTAMP_FEATURE
5381 goto err_bap_stop;
5382#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005383 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005384#endif //WLAN_BTAMP_FEATURE
5385 }
5386
5387 /* Register TM level change handler function to the platform */
5388 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5389 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5390 {
5391 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5392 goto err_unregister_pmops;
5393 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005394
5395 /* register for riva power on lock to platform driver */
5396 if (req_riva_power_on_lock("wlan"))
5397 {
5398 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5399 __func__);
5400 goto err_unregister_pmops;
5401 }
5402
Jeff Johnson295189b2012-06-20 16:38:30 -07005403 // register net device notifier for device change notification
5404 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5405
5406 if(ret < 0)
5407 {
5408 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5409 goto err_free_power_on_lock;
5410 }
5411
5412 //Initialize the nlink service
5413 if(nl_srv_init() != 0)
5414 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305415 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005416 goto err_reg_netdev;
5417 }
5418
5419 //Initialize the BTC service
5420 if(btc_activate_service(pHddCtx) != 0)
5421 {
5422 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5423 goto err_nl_srv;
5424 }
5425
5426#ifdef PTT_SOCK_SVC_ENABLE
5427 //Initialize the PTT service
5428 if(ptt_sock_activate_svc(pHddCtx) != 0)
5429 {
5430 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5431 goto err_nl_srv;
5432 }
5433#endif
5434
Jeff Johnson295189b2012-06-20 16:38:30 -07005435 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005436 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005437 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005438 /* Action frame registered in one adapter which will
5439 * applicable to all interfaces
5440 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005441 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005442 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005443
5444 mutex_init(&pHddCtx->sap_lock);
5445
5446 pHddCtx->isLoadUnloadInProgress = FALSE;
5447
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005448#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005449#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5450 /* Initialize the wake lcok */
5451 wake_lock_init(&pHddCtx->rx_wake_lock,
5452 WAKE_LOCK_SUSPEND,
5453 "qcom_rx_wakelock");
5454#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005455 /* Initialize the wake lcok */
5456 wake_lock_init(&pHddCtx->sap_wake_lock,
5457 WAKE_LOCK_SUSPEND,
5458 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005459#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005460
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005461 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5462 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005463
5464 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5465 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005466
5467 // Initialize the restart logic
5468 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305469
Jeff Johnson295189b2012-06-20 16:38:30 -07005470 goto success;
5471
5472err_nl_srv:
5473 nl_srv_exit();
5474
5475err_reg_netdev:
5476 unregister_netdevice_notifier(&hdd_netdev_notifier);
5477
5478err_free_power_on_lock:
5479 free_riva_power_on_lock("wlan");
5480
5481err_unregister_pmops:
5482 hddDevTmUnregisterNotifyCallback(pHddCtx);
5483 hddDeregisterPmOps(pHddCtx);
5484
5485#ifdef WLAN_BTAMP_FEATURE
5486err_bap_stop:
5487 WLANBAP_Stop(pVosContext);
5488#endif
5489
5490#ifdef WLAN_BTAMP_FEATURE
5491err_bap_close:
5492 WLANBAP_Close(pVosContext);
5493#endif
5494
Jeff Johnson295189b2012-06-20 16:38:30 -07005495err_close_adapter:
5496 hdd_close_all_adapters( pHddCtx );
5497
5498err_vosstop:
5499 vos_stop(pVosContext);
5500
5501err_vosclose:
5502 status = vos_sched_close( pVosContext );
5503 if (!VOS_IS_STATUS_SUCCESS(status)) {
5504 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5505 "%s: Failed to close VOSS Scheduler", __func__);
5506 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5507 }
5508 vos_close(pVosContext );
5509
Jeff Johnson295189b2012-06-20 16:38:30 -07005510err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005511 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005512
5513err_wdclose:
5514 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5515 vos_watchdog_close(pVosContext);
5516
Jeff Johnson295189b2012-06-20 16:38:30 -07005517err_wiphy_reg:
5518 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005519
5520err_config:
5521 kfree(pHddCtx->cfg_ini);
5522 pHddCtx->cfg_ini= NULL;
5523
5524err_free_hdd_context:
5525 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005526 wiphy_free(wiphy) ;
5527 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005528 VOS_BUG(1);
5529
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005530 if (hdd_is_ssr_required())
5531 {
5532 /* WDI timeout had happened during load, so SSR is needed here */
5533 subsystem_restart("wcnss");
5534 msleep(5000);
5535 }
5536 hdd_set_ssr_required (VOS_FALSE);
5537
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005538 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005539
5540success:
5541 EXIT();
5542 return 0;
5543}
5544
5545/**---------------------------------------------------------------------------
5546
Jeff Johnson32d95a32012-09-10 13:15:23 -07005547 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07005548
Jeff Johnson32d95a32012-09-10 13:15:23 -07005549 This is the driver entry point - called in different timeline depending
5550 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07005551
5552 \param - None
5553
5554 \return - 0 for success, non zero for failure
5555
5556 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07005557static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005558{
5559 VOS_STATUS status;
5560 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005561 struct device *dev = NULL;
5562 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005563#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5564 int max_retries = 0;
5565#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005566
Gopichand Nakkalad0774962013-05-24 11:32:21 +05305567#ifdef WCONN_TRACE_KMSG_LOG_BUFF
5568 vos_wconn_trace_init();
5569#endif
5570
Jeff Johnson295189b2012-06-20 16:38:30 -07005571 ENTER();
5572
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005573#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005574 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07005575#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005576
5577 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
5578 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
5579
5580 //Power Up Libra WLAN card first if not already powered up
5581 status = vos_chipPowerUp(NULL,NULL,NULL);
5582 if (!VOS_IS_STATUS_SUCCESS(status))
5583 {
5584 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
5585 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005586 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005587 }
5588
Jeff Johnson295189b2012-06-20 16:38:30 -07005589#ifdef ANI_BUS_TYPE_PCI
5590
5591 dev = wcnss_wlan_get_device();
5592
5593#endif // ANI_BUS_TYPE_PCI
5594
5595#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005596
5597#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5598 /* wait until WCNSS driver downloads NV */
5599 while (!wcnss_device_ready() && 5 >= ++max_retries) {
5600 msleep(1000);
5601 }
5602 if (max_retries >= 5) {
5603 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
5604 return -ENODEV;
5605 }
5606#endif
5607
Jeff Johnson295189b2012-06-20 16:38:30 -07005608 dev = wcnss_wlan_get_device();
5609#endif // ANI_BUS_TYPE_PLATFORM
5610
5611
5612 do {
5613 if (NULL == dev) {
5614 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
5615 ret_status = -1;
5616 break;
5617 }
5618
5619#ifdef MEMORY_DEBUG
5620 vos_mem_init();
5621#endif
5622
5623#ifdef TIMER_MANAGER
5624 vos_timer_manager_init();
5625#endif
5626
5627 /* Preopen VOSS so that it is ready to start at least SAL */
5628 status = vos_preOpen(&pVosContext);
5629
5630 if (!VOS_IS_STATUS_SUCCESS(status))
5631 {
5632 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
5633 ret_status = -1;
5634 break;
5635 }
5636
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005637#ifndef MODULE
5638 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
5639 */
5640 hdd_set_conparam((v_UINT_t)con_mode);
5641#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005642
5643 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005644 if (hdd_wlan_startup(dev))
5645 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005646 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005647 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005648 vos_preClose( &pVosContext );
5649 ret_status = -1;
5650 break;
5651 }
5652
5653 /* Cancel the vote for XO Core ON
5654 * This is done here for safety purposes in case we re-initialize without turning
5655 * it OFF in any error scenario.
5656 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005657 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07005658 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005659 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07005660 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5661 {
5662 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
5663 " Power consumed will be high\n");
5664 }
5665 } while (0);
5666
5667 if (0 != ret_status)
5668 {
5669 //Assert Deep sleep signal now to put Libra HW in lowest power state
5670 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5671 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
5672
5673 //Vote off any PMIC voltage supplies
5674 vos_chipPowerDown(NULL, NULL, NULL);
5675#ifdef TIMER_MANAGER
5676 vos_timer_exit();
5677#endif
5678#ifdef MEMORY_DEBUG
5679 vos_mem_exit();
5680#endif
5681
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005682#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005683 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005684#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005685 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
5686 }
5687 else
5688 {
5689 //Send WLAN UP indication to Nlink Service
5690 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
5691
5692 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
5693
5694 }
5695
5696 EXIT();
5697
5698 return ret_status;
5699}
5700
Jeff Johnson32d95a32012-09-10 13:15:23 -07005701/**---------------------------------------------------------------------------
5702
5703 \brief hdd_module_init() - Init Function
5704
5705 This is the driver entry point (invoked when module is loaded using insmod)
5706
5707 \param - None
5708
5709 \return - 0 for success, non zero for failure
5710
5711 --------------------------------------------------------------------------*/
5712#ifdef MODULE
5713static int __init hdd_module_init ( void)
5714{
5715 return hdd_driver_init();
5716}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005717#else /* #ifdef MODULE */
5718static int __init hdd_module_init ( void)
5719{
5720 /* Driver initialization is delayed to fwpath_changed_handler */
5721 return 0;
5722}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005723#endif /* #ifdef MODULE */
5724
Jeff Johnson295189b2012-06-20 16:38:30 -07005725
5726/**---------------------------------------------------------------------------
5727
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005728 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005729
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005730 This is the driver exit point (invoked when module is unloaded using rmmod
5731 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07005732
5733 \param - None
5734
5735 \return - None
5736
5737 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005738static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005739{
5740 hdd_context_t *pHddCtx = NULL;
5741 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005742
5743 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
5744
5745 //Get the global vos context
5746 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5747
5748 if(!pVosContext)
5749 {
5750 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
5751 goto done;
5752 }
5753
5754 //Get the HDD context.
5755 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
5756
5757 if(!pHddCtx)
5758 {
5759 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
5760 }
5761 else
5762 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005763 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07005764 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07005765 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
5766 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07005767 }
5768
5769 pHddCtx->isLoadUnloadInProgress = TRUE;
5770 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5771
5772 //Do all the cleanup before deregistering the driver
5773 hdd_wlan_exit(pHddCtx);
5774 }
5775
Jeff Johnson295189b2012-06-20 16:38:30 -07005776 vos_preClose( &pVosContext );
5777
5778#ifdef TIMER_MANAGER
5779 vos_timer_exit();
5780#endif
5781#ifdef MEMORY_DEBUG
5782 vos_mem_exit();
5783#endif
5784
Gopichand Nakkalad0774962013-05-24 11:32:21 +05305785#ifdef WCONN_TRACE_KMSG_LOG_BUFF
5786 vos_wconn_trace_exit();
5787#endif
5788
Jeff Johnson295189b2012-06-20 16:38:30 -07005789done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005790#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005791 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005792#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005793 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
5794}
5795
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005796/**---------------------------------------------------------------------------
5797
5798 \brief hdd_module_exit() - Exit function
5799
5800 This is the driver exit point (invoked when module is unloaded using rmmod)
5801
5802 \param - None
5803
5804 \return - None
5805
5806 --------------------------------------------------------------------------*/
5807static void __exit hdd_module_exit(void)
5808{
5809 hdd_driver_exit();
5810}
5811
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005812#ifdef MODULE
5813static int fwpath_changed_handler(const char *kmessage,
5814 struct kernel_param *kp)
5815{
Jeff Johnson76052702013-04-16 13:55:05 -07005816 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005817}
5818
5819static int con_mode_handler(const char *kmessage,
5820 struct kernel_param *kp)
5821{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07005822 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005823}
5824#else /* #ifdef MODULE */
5825/**---------------------------------------------------------------------------
5826
Jeff Johnson76052702013-04-16 13:55:05 -07005827 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005828
Jeff Johnson76052702013-04-16 13:55:05 -07005829 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005830 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07005831 - invoked when module parameter fwpath is modified from userspace to signal
5832 initializing the WLAN driver or when con_mode is modified from userspace
5833 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005834
5835 \return - 0 for success, non zero for failure
5836
5837 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07005838static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005839{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005840 int ret_status;
5841
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005842 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005843 ret_status = hdd_driver_init();
5844 wlan_hdd_inited = ret_status ? 0 : 1;
5845 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005846 }
5847
5848 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07005849
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005850 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07005851
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005852 ret_status = hdd_driver_init();
5853 wlan_hdd_inited = ret_status ? 0 : 1;
5854 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005855}
5856
Jeff Johnson295189b2012-06-20 16:38:30 -07005857/**---------------------------------------------------------------------------
5858
Jeff Johnson76052702013-04-16 13:55:05 -07005859 \brief fwpath_changed_handler() - Handler Function
5860
5861 Handle changes to the fwpath parameter
5862
5863 \return - 0 for success, non zero for failure
5864
5865 --------------------------------------------------------------------------*/
5866static int fwpath_changed_handler(const char *kmessage,
5867 struct kernel_param *kp)
5868{
5869 int ret;
5870
5871 ret = param_set_copystring(kmessage, kp);
5872 if (0 == ret)
5873 ret = kickstart_driver();
5874 return ret;
5875}
5876
5877/**---------------------------------------------------------------------------
5878
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005879 \brief con_mode_handler() -
5880
5881 Handler function for module param con_mode when it is changed by userspace
5882 Dynamically linked - do nothing
5883 Statically linked - exit and init driver, as in rmmod and insmod
5884
Jeff Johnson76052702013-04-16 13:55:05 -07005885 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005886
Jeff Johnson76052702013-04-16 13:55:05 -07005887 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005888
5889 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07005890static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005891{
Jeff Johnson76052702013-04-16 13:55:05 -07005892 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005893
Jeff Johnson76052702013-04-16 13:55:05 -07005894 ret = param_set_int(kmessage, kp);
5895 if (0 == ret)
5896 ret = kickstart_driver();
5897 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005898}
5899#endif /* #ifdef MODULE */
5900
5901/**---------------------------------------------------------------------------
5902
Jeff Johnson295189b2012-06-20 16:38:30 -07005903 \brief hdd_get_conparam() -
5904
5905 This is the driver exit point (invoked when module is unloaded using rmmod)
5906
5907 \param - None
5908
5909 \return - tVOS_CON_MODE
5910
5911 --------------------------------------------------------------------------*/
5912tVOS_CON_MODE hdd_get_conparam ( void )
5913{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005914#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07005915 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005916#else
5917 return (tVOS_CON_MODE)curr_con_mode;
5918#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005919}
5920void hdd_set_conparam ( v_UINT_t newParam )
5921{
5922 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005923#ifndef MODULE
5924 curr_con_mode = con_mode;
5925#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005926}
5927/**---------------------------------------------------------------------------
5928
5929 \brief hdd_softap_sta_deauth() - function
5930
5931 This to take counter measure to handle deauth req from HDD
5932
5933 \param - pAdapter - Pointer to the HDD
5934
5935 \param - enable - boolean value
5936
5937 \return - None
5938
5939 --------------------------------------------------------------------------*/
5940
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005941VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07005942{
Jeff Johnson295189b2012-06-20 16:38:30 -07005943 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005944 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07005945
5946 ENTER();
5947
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305948 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07005949
5950 //Ignore request to deauth bcmc station
5951 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005952 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005953
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005954 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07005955
5956 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005957 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005958}
5959
5960/**---------------------------------------------------------------------------
5961
5962 \brief hdd_softap_sta_disassoc() - function
5963
5964 This to take counter measure to handle deauth req from HDD
5965
5966 \param - pAdapter - Pointer to the HDD
5967
5968 \param - enable - boolean value
5969
5970 \return - None
5971
5972 --------------------------------------------------------------------------*/
5973
5974void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
5975{
5976 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5977
5978 ENTER();
5979
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305980 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07005981
5982 //Ignore request to disassoc bcmc station
5983 if( pDestMacAddress[0] & 0x1 )
5984 return;
5985
5986 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
5987}
5988
5989void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
5990{
5991 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5992
5993 ENTER();
5994
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305995 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07005996
5997 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
5998}
5999
Jeff Johnson295189b2012-06-20 16:38:30 -07006000/**---------------------------------------------------------------------------
6001 *
6002 * \brief hdd_get__concurrency_mode() -
6003 *
6004 *
6005 * \param - None
6006 *
6007 * \return - CONCURRENCY MODE
6008 *
6009 * --------------------------------------------------------------------------*/
6010tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
6011{
6012 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
6013 hdd_context_t *pHddCtx;
6014
6015 if (NULL != pVosContext)
6016 {
6017 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
6018 if (NULL != pHddCtx)
6019 {
6020 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
6021 }
6022 }
6023
6024 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006025 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006026 return VOS_STA;
6027}
6028
6029/* Decide whether to allow/not the apps power collapse.
6030 * Allow apps power collapse if we are in connected state.
6031 * if not, allow only if we are in IMPS */
6032v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
6033{
6034 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08006035 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006036 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07006037 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6038 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6039 hdd_adapter_t *pAdapter = NULL;
6040 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08006041 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006042
Jeff Johnson295189b2012-06-20 16:38:30 -07006043 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6044 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006045
Yathish9f22e662012-12-10 14:21:35 -08006046 concurrent_state = hdd_get_concurrency_mode();
6047
6048#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6049 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
6050 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
6051 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
6052 return TRUE;
6053#endif
6054
Jeff Johnson295189b2012-06-20 16:38:30 -07006055 /*loop through all adapters. TBD fix for Concurrency */
6056 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6057 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6058 {
6059 pAdapter = pAdapterNode->pAdapter;
6060 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
6061 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6062 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006063 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07006064 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08006065 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006066 (eANI_BOOLEAN_TRUE == scanRspPending) ||
6067 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07006068 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08006069 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08006070 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
6071 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07006072 return FALSE;
6073 }
6074 }
6075 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6076 pAdapterNode = pNext;
6077 }
6078 return TRUE;
6079}
6080
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08006081/* Decides whether to send suspend notification to Riva
6082 * if any adapter is in BMPS; then it is required */
6083v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
6084{
6085 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
6086 hdd_config_t *pConfig = pHddCtx->cfg_ini;
6087
6088 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
6089 {
6090 return TRUE;
6091 }
6092 return FALSE;
6093}
6094
Jeff Johnson295189b2012-06-20 16:38:30 -07006095void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6096{
6097 switch(mode)
6098 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006099 case VOS_STA_MODE:
6100 case VOS_P2P_CLIENT_MODE:
6101 case VOS_P2P_GO_MODE:
6102 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07006103 pHddCtx->concurrency_mode |= (1 << mode);
6104 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07006105 break;
6106 default:
6107 break;
6108
6109 }
6110 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6111 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6112}
6113
6114
6115void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
6116{
6117 switch(mode)
6118 {
Chilam Ngc4244af2013-04-01 15:37:32 -07006119 case VOS_STA_MODE:
6120 case VOS_P2P_CLIENT_MODE:
6121 case VOS_P2P_GO_MODE:
6122 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006123 pHddCtx->no_of_sessions[mode]--;
6124 if (!(pHddCtx->no_of_sessions[mode]))
6125 pHddCtx->concurrency_mode &= (~(1 << mode));
6126 break;
6127 default:
6128 break;
6129 }
6130 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
6131 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
6132}
6133
Jeff Johnsone7245742012-09-05 17:12:55 -07006134/**---------------------------------------------------------------------------
6135 *
6136 * \brief wlan_hdd_restart_init
6137 *
6138 * This function initalizes restart timer/flag. An internal function.
6139 *
6140 * \param - pHddCtx
6141 *
6142 * \return - None
6143 *
6144 * --------------------------------------------------------------------------*/
6145
6146static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
6147{
6148 /* Initialize */
6149 pHddCtx->hdd_restart_retries = 0;
6150 atomic_set(&pHddCtx->isRestartInProgress, 0);
6151 vos_timer_init(&pHddCtx->hdd_restart_timer,
6152 VOS_TIMER_TYPE_SW,
6153 wlan_hdd_restart_timer_cb,
6154 pHddCtx);
6155}
6156/**---------------------------------------------------------------------------
6157 *
6158 * \brief wlan_hdd_restart_deinit
6159 *
6160 * This function cleans up the resources used. An internal function.
6161 *
6162 * \param - pHddCtx
6163 *
6164 * \return - None
6165 *
6166 * --------------------------------------------------------------------------*/
6167
6168static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
6169{
6170
6171 VOS_STATUS vos_status;
6172 /* Block any further calls */
6173 atomic_set(&pHddCtx->isRestartInProgress, 1);
6174 /* Cleanup */
6175 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
6176 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006177 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006178 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
6179 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07006180 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07006181
6182}
6183
6184/**---------------------------------------------------------------------------
6185 *
6186 * \brief wlan_hdd_framework_restart
6187 *
6188 * This function uses a cfg80211 API to start a framework initiated WLAN
6189 * driver module unload/load.
6190 *
6191 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6192 *
6193 *
6194 * \param - pHddCtx
6195 *
6196 * \return - VOS_STATUS_SUCCESS: Success
6197 * VOS_STATUS_E_EMPTY: Adapter is Empty
6198 * VOS_STATUS_E_NOMEM: No memory
6199
6200 * --------------------------------------------------------------------------*/
6201
6202static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6203{
6204 VOS_STATUS status = VOS_STATUS_SUCCESS;
6205 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006206 int len = (sizeof (struct ieee80211_mgmt));
6207 struct ieee80211_mgmt *mgmt = NULL;
6208
6209 /* Prepare the DEAUTH managment frame with reason code */
6210 mgmt = kzalloc(len, GFP_KERNEL);
6211 if(mgmt == NULL)
6212 {
6213 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6214 "%s: memory allocation failed (%d bytes)", __func__, len);
6215 return VOS_STATUS_E_NOMEM;
6216 }
6217 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006218
6219 /* Iterate over all adapters/devices */
6220 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6221 do
6222 {
6223 if( (status == VOS_STATUS_SUCCESS) &&
6224 pAdapterNode &&
6225 pAdapterNode->pAdapter)
6226 {
6227 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6228 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6229 pAdapterNode->pAdapter->dev->name,
6230 pAdapterNode->pAdapter->device_mode,
6231 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006232 /*
6233 * CFG80211 event to restart the driver
6234 *
6235 * 'cfg80211_send_unprot_deauth' sends a
6236 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6237 * of SME(Linux Kernel) state machine.
6238 *
6239 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6240 * the driver.
6241 *
6242 */
6243
6244 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006245 }
6246 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6247 pAdapterNode = pNext;
6248 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6249
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006250
6251 /* Free the allocated management frame */
6252 kfree(mgmt);
6253
Jeff Johnsone7245742012-09-05 17:12:55 -07006254 /* Retry until we unload or reach max count */
6255 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6256 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6257
6258 return status;
6259
6260}
6261/**---------------------------------------------------------------------------
6262 *
6263 * \brief wlan_hdd_restart_timer_cb
6264 *
6265 * Restart timer callback. An internal function.
6266 *
6267 * \param - User data:
6268 *
6269 * \return - None
6270 *
6271 * --------------------------------------------------------------------------*/
6272
6273void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6274{
6275 hdd_context_t *pHddCtx = usrDataForCallback;
6276 wlan_hdd_framework_restart(pHddCtx);
6277 return;
6278
6279}
6280
6281
6282/**---------------------------------------------------------------------------
6283 *
6284 * \brief wlan_hdd_restart_driver
6285 *
6286 * This function sends an event to supplicant to restart the WLAN driver.
6287 *
6288 * This function is called from vos_wlanRestart.
6289 *
6290 * \param - pHddCtx
6291 *
6292 * \return - VOS_STATUS_SUCCESS: Success
6293 * VOS_STATUS_E_EMPTY: Adapter is Empty
6294 * VOS_STATUS_E_ALREADY: Request already in progress
6295
6296 * --------------------------------------------------------------------------*/
6297VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6298{
6299 VOS_STATUS status = VOS_STATUS_SUCCESS;
6300
6301 /* A tight check to make sure reentrancy */
6302 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6303 {
6304 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6305 "%s: WLAN restart is already in progress", __func__);
6306
6307 return VOS_STATUS_E_ALREADY;
6308 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006309 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006310#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006311 wcnss_reset_intr();
6312#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006313
Jeff Johnsone7245742012-09-05 17:12:55 -07006314 return status;
6315}
6316
6317
Jeff Johnson295189b2012-06-20 16:38:30 -07006318//Register the module init/exit functions
6319module_init(hdd_module_init);
6320module_exit(hdd_module_exit);
6321
6322MODULE_LICENSE("Dual BSD/GPL");
6323MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6324MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6325
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006326module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6327 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006328
Jeff Johnson76052702013-04-16 13:55:05 -07006329module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006330 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);