blob: f396ed201290cfddbc0a65be6acbb8722135b821 [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
104#ifdef CONFIG_CFG80211
105#include <linux/wireless.h>
106#include <net/cfg80211.h>
107#include "wlan_hdd_cfg80211.h"
108#include "wlan_hdd_p2p.h"
109#endif
110#include <linux/rtnetlink.h>
111#ifdef ANI_MANF_DIAG
112int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
113#endif
114#ifdef WLAN_SOFTAP_FEATURE
115#include "sapApi.h"
116#include <linux/semaphore.h>
117#include <mach/subsystem_restart.h>
118#include <wlan_hdd_hostapd.h>
119#include <wlan_hdd_softap_tx_rx.h>
120#endif
121#ifdef FEATURE_WLAN_INTEGRATED_SOC
122#include "cfgApi.h"
123#endif
124#include "wlan_hdd_dev_pwr.h"
125#ifdef WLAN_BTAMP_FEATURE
126#include "bap_hdd_misc.h"
127#endif
128#ifdef FEATURE_WLAN_INTEGRATED_SOC
129#include "wlan_qct_pal_trace.h"
130#endif /* FEATURE_WLAN_INTEGRATED_SOC */
131#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800132#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530133#ifdef FEATURE_WLAN_TDLS
134#include "wlan_hdd_tdls.h"
135#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700136
137#ifdef MODULE
138#define WLAN_MODULE_NAME module_name(THIS_MODULE)
139#else
140#define WLAN_MODULE_NAME "wlan"
141#endif
142
143#ifdef TIMER_MANAGER
144#define TIMER_MANAGER_STR " +TIMER_MANAGER"
145#else
146#define TIMER_MANAGER_STR ""
147#endif
148
149#ifdef MEMORY_DEBUG
150#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
151#else
152#define MEMORY_DEBUG_STR ""
153#endif
154
155/* the Android framework expects this param even though we don't use it */
156#define BUF_LEN 20
157static char fwpath[BUF_LEN];
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700158#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700159static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700160#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700161
Jeff Johnsone7245742012-09-05 17:12:55 -0700162/*
163 * The rate at which the driver sends RESTART event to supplicant
164 * once the function 'vos_wlanRestart()' is called
165 *
166 */
167#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
168#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800169#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700170static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700171#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700172/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700173static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700174
175//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700176static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
177static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
178static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
179void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800180void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700181
Jeff Johnson295189b2012-06-20 16:38:30 -0700182v_U16_t hdd_select_queue(struct net_device *dev,
183 struct sk_buff *skb);
184
185#ifdef WLAN_FEATURE_PACKET_FILTERING
186static void hdd_set_multicast_list(struct net_device *dev);
187#endif
188
189void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
190
191extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800192#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
193void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
194static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
195static VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
196#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700197static int hdd_netdev_notifier_call(struct notifier_block * nb,
198 unsigned long state,
199 void *ndev)
200{
201 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700202 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
203 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -0700204#ifdef WLAN_BTAMP_FEATURE
205 VOS_STATUS status;
206 hdd_context_t *pHddCtx;
207#endif
208
209 //Make sure that this callback corresponds to our device.
210 if((strncmp( dev->name, "wlan", 4 )) &&
Jeff Johnsone7245742012-09-05 17:12:55 -0700211 (strncmp( dev->name, "p2p", 3))
Jeff Johnson295189b2012-06-20 16:38:30 -0700212 )
213 return NOTIFY_DONE;
214
215#ifdef CONFIG_CFG80211
216 if (!dev->ieee80211_ptr)
217 return NOTIFY_DONE;
218#endif
219
Jeff Johnson295189b2012-06-20 16:38:30 -0700220
221 if(NULL == pAdapter)
222 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800223 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700224 VOS_ASSERT(0);
225 return NOTIFY_DONE;
226 }
227
228 hddLog(VOS_TRACE_LEVEL_INFO,"%s: New Net Device State = %lu", __func__, state);
229
230 switch (state) {
231 case NETDEV_REGISTER:
232 break;
233
234 case NETDEV_UNREGISTER:
235 break;
236
237 case NETDEV_UP:
238 break;
239
240 case NETDEV_DOWN:
241 break;
242
243 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700244 if(TRUE == pAdapter->isLinkUpSvcNeeded)
245 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700246 break;
247
248 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700249 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700250 {
251 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800252 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700253 hdd_abort_mac_scan(pAdapter->pHddCtx);
254 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800255 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700256 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
257 if(!result)
258 {
259 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800260 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700261 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700262 }
263 }
264 else
265 {
266 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700267 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700268 }
269#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700270 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700271 status = WLANBAP_StopAmp();
272 if(VOS_STATUS_SUCCESS != status )
273 {
274 pHddCtx->isAmpAllowed = VOS_TRUE;
275 hddLog(VOS_TRACE_LEVEL_FATAL,
276 "%s: Failed to stop AMP", __func__);
277 }
278 else
279 {
280 //a state m/c implementation in PAL is TBD to avoid this delay
281 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700282 if ( pHddCtx->isAmpAllowed )
283 {
284 WLANBAP_DeregisterFromHCI();
285 pHddCtx->isAmpAllowed = VOS_FALSE;
286 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700287 }
288#endif //WLAN_BTAMP_FEATURE
289 break;
290
291 default:
292 break;
293 }
294
295 return NOTIFY_DONE;
296}
297
298struct notifier_block hdd_netdev_notifier = {
299 .notifier_call = hdd_netdev_notifier_call,
300};
301
302/*---------------------------------------------------------------------------
303 * Function definitions
304 *-------------------------------------------------------------------------*/
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800305int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700306void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
307void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700308//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700309static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700310#ifndef MODULE
311/* current con_mode - used only for statically linked driver
312 * con_mode is changed by userspace to indicate a mode change which will
313 * result in calling the module exit and init functions. The module
314 * exit function will clean up based on the value of con_mode prior to it
315 * being changed by userspace. So curr_con_mode records the current con_mode
316 * for exit when con_mode becomes the next mode for init
317 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700318static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700319#endif
320
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800321/**---------------------------------------------------------------------------
322
323 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
324
325 Called immediately after the cfg.ini is read in order to configure
326 the desired trace levels.
327
328 \param - moduleId - module whose trace level is being configured
329 \param - bitmask - bitmask of log levels to be enabled
330
331 \return - void
332
333 --------------------------------------------------------------------------*/
334static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
335{
336 wpt_tracelevel level;
337
338 /* if the bitmask is the default value, then a bitmask was not
339 specified in cfg.ini, so leave the logging level alone (it
340 will remain at the "compiled in" default value) */
341 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
342 {
343 return;
344 }
345
346 /* a mask was specified. start by disabling all logging */
347 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
348
349 /* now cycle through the bitmask until all "set" bits are serviced */
350 level = VOS_TRACE_LEVEL_FATAL;
351 while (0 != bitmask)
352 {
353 if (bitmask & 1)
354 {
355 vos_trace_setValue(moduleId, level, 1);
356 }
357 level++;
358 bitmask >>= 1;
359 }
360}
361
362
Jeff Johnson295189b2012-06-20 16:38:30 -0700363#ifdef FEATURE_WLAN_INTEGRATED_SOC
364/**---------------------------------------------------------------------------
365
366 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
367
368 Called immediately after the cfg.ini is read in order to configure
369 the desired trace levels in the WDI.
370
371 \param - moduleId - module whose trace level is being configured
372 \param - bitmask - bitmask of log levels to be enabled
373
374 \return - void
375
376 --------------------------------------------------------------------------*/
377static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
378{
379 wpt_tracelevel level;
380
381 /* if the bitmask is the default value, then a bitmask was not
382 specified in cfg.ini, so leave the logging level alone (it
383 will remain at the "compiled in" default value) */
384 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
385 {
386 return;
387 }
388
389 /* a mask was specified. start by disabling all logging */
390 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
391
392 /* now cycle through the bitmask until all "set" bits are serviced */
393 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
394 while (0 != bitmask)
395 {
396 if (bitmask & 1)
397 {
398 wpalTraceSetLevel(moduleId, level, 1);
399 }
400 level++;
401 bitmask >>= 1;
402 }
403}
404#endif /* FEATURE_WLAN_INTEGRATED_SOC */
405
406int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
407{
408 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
409 hdd_priv_data_t priv_data;
410 tANI_U8 *command = NULL;
411 int ret = 0;
412
413 if (NULL == pAdapter)
414 {
415 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700416 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700417 ret = -ENODEV;
418 goto exit;
419 }
420
Jeff Johnsone7245742012-09-05 17:12:55 -0700421 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700422 {
423 ret = -EINVAL;
424 goto exit;
425 }
426
427 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
428 {
429 ret = -EFAULT;
430 goto exit;
431 }
432
433 command = kmalloc(priv_data.total_len, GFP_KERNEL);
434 if (!command)
435 {
436 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700437 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700438 ret = -ENOMEM;
439 goto exit;
440 }
441
442 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
443 {
444 ret = -EFAULT;
445 goto exit;
446 }
447
448 if ((SIOCDEVPRIVATE + 1) == cmd)
449 {
450 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
451
452 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700453 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700454
455 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
456 {
457 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
458 sizeof(tSirMacAddr)))
459 {
460 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700461 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700462 ret = -EFAULT;
463 }
464 }
Amar Singhal0974e402013-02-12 14:27:46 -0800465 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700466 {
Amar Singhal0974e402013-02-12 14:27:46 -0800467 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700468 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800469
Jeff Johnson295189b2012-06-20 16:38:30 -0700470 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800471
472 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700473 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700474 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800475 "%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 -0700476 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800477 ret = hdd_setBand_helper(dev, ptr);
478 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700479 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
480 {
481 char *country_code;
482
483 country_code = command + 8;
484 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
485 pAdapter, pHddCtx->pvosContext);
486 if( 0 != ret )
487 {
488 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
489 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
490
491 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700492 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800493#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
494 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
495 {
496 tANI_U8 *value = command;
497 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
498 tANI_U8 revision = 0;
499 eHalStatus status = eHAL_STATUS_SUCCESS;
500 v_REGDOMAIN_t regId;
501
502 status = hdd_parse_countryrev(value, countryCode, &revision);
503 if (eHAL_STATUS_SUCCESS != status)
504 {
505 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
506 "%s: Failed to parse country revision information", __func__);
507 ret = -EINVAL;
508 goto exit;
509 }
510
511 /* Validate country code */
512 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
513 if (eHAL_STATUS_SUCCESS != status)
514 {
515 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
516 "%s: Invalid country code %s", __func__, countryCode);
517 ret = -EINVAL;
518 goto exit;
519 }
520
521 /* Validate revision */
522 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
523 {
524 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
525 "%s: Invalid revision %d", __func__, revision);
526 ret = -EINVAL;
527 goto exit;
528 }
529
530 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
531 pAdapter, pHddCtx->pvosContext);
532 if (0 != ret)
533 {
534 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
535 "%s: SME Change Country code fail ret=%d", __func__, ret);
536 ret = -EINVAL;
537 goto exit;
538 }
539
540 if (0 == strncmp(countryCode, "KR", 2))
541 {
542 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
543 revision);
544 if (eHAL_STATUS_SUCCESS != status)
545 {
546 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
547 "%s: Failed to build valid channel list", __func__);
548 ret = -EINVAL;
549 goto exit;
550 }
551 }
552 }
553#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700554 /*
555 command should be a string having format
556 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
557 */
Amar Singhal0974e402013-02-12 14:27:46 -0800558 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700559 {
Amar Singhal0974e402013-02-12 14:27:46 -0800560 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700561
562 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700563 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700564
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800565 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700566 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800567 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
568 {
569 int suspend = 0;
570 tANI_U8 *ptr = (tANI_U8*)command + 15;
571
572 suspend = *ptr - '0';
573 hdd_set_wlan_suspend_mode(suspend);
574 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800575#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
576 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
577 {
578 tANI_U8 *value = command;
579 int rssi = 0;
580 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
581 eHalStatus status = eHAL_STATUS_SUCCESS;
582
583 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
584 value = value + 15;
585
586 sscanf(value, "%d", &rssi);
587 lookUpThreshold = abs(rssi);
588 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
589 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
590 {
591 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
592 "Neighbor lookup threshold value %d is out of range"
593 " (Min: %d Max: %d)", lookUpThreshold,
594 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
595 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
596 ret = -EINVAL;
597 goto exit;
598 }
599
600 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
601 "%s: Received Command to Set Roam trigger"
602 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
603
604 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
605 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
606 if (eHAL_STATUS_SUCCESS != status)
607 {
608 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
609 "%s: Failed to set roam trigger, try again", __func__);
610 ret = -EPERM;
611 goto exit;
612 }
613
614 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
615 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
616 }
617 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
618 {
619 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
620 int rssi = (-1) * lookUpThreshold;
621 char extra[32];
622 tANI_U8 len = 0;
623
624 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
625 if (copy_to_user(priv_data.buf, &extra, len + 1))
626 {
627 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
628 "%s: failed to copy data to user buffer", __func__);
629 ret = -EFAULT;
630 goto exit;
631 }
632 }
633 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
634 {
635 tANI_U8 *value = command;
636 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
637 /* input refresh period is in terms of seconds */
638 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
639 value = value + 18;
640 /* Convert the value from ascii to integer */
641 ret = kstrtou16(value, 10, &neighborScanRefreshPeriod);
642 if (ret < 0)
643 {
644 /* If the input value is greater than max value of datatype, then also
645 kstrtou16 fails */
646 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
647 "%s: kstrtou16 failed ",
648 "Input value may be out of range[%d - %d]",
649 __func__,
650 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
651 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
652 ret = -EINVAL;
653 goto exit;
654 }
655
656 neighborScanRefreshPeriod = neighborScanRefreshPeriod * 1000;
657 if ((neighborScanRefreshPeriod < CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN) ||
658 (neighborScanRefreshPeriod > CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX))
659 {
660 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
661 "Neighbor scan results refresh period value %d is out of range"
662 " (Min: %d Max: %d)", neighborScanRefreshPeriod,
663 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
664 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
665 ret = -EINVAL;
666 goto exit;
667 }
668
669 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
670 "%s: Received Command to Set roam scan period"
671 " (Neighbor Scan refresh period) = %d", __func__, neighborScanRefreshPeriod);
672
673 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborScanRefreshPeriod;
674 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
675 }
676 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
677 {
678 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
679 char extra[32];
680 tANI_U8 len = 0;
681
682 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
683 /* Returned value is in units of seconds */
684 if (copy_to_user(priv_data.buf, &extra, len + 1))
685 {
686 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
687 "%s: failed to copy data to user buffer", __func__);
688 ret = -EFAULT;
689 goto exit;
690 }
691 }
692#endif
693#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
694 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
695 {
696 tANI_U8 *value = command;
697 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
698
699 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
700 value = value + 13;
701 /* Convert the value from ascii to integer */
702 ret = kstrtou8(value, 10, &roamRssiDiff);
703 if (ret < 0)
704 {
705 /* If the input value is greater than max value of datatype, then also
706 kstrtou8 fails */
707 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
708 "%s: kstrtou8 failed range [%d - %d]", __func__,
709 CFG_ROAM_RSSI_DIFF_MIN,
710 CFG_ROAM_RSSI_DIFF_MAX);
711 ret = -EINVAL;
712 goto exit;
713 }
714
715 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
716 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
717 {
718 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
719 "Roam rssi diff value %d is out of range"
720 " (Min: %d Max: %d)", roamRssiDiff,
721 CFG_ROAM_RSSI_DIFF_MIN,
722 CFG_ROAM_RSSI_DIFF_MAX);
723 ret = -EINVAL;
724 goto exit;
725 }
726
727 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
728 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
729
730 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
731 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
732 }
733 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
734 {
735 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
736 char extra[32];
737 tANI_U8 len = 0;
738
739 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
740 if (copy_to_user(priv_data.buf, &extra, len + 1))
741 {
742 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
743 "%s: failed to copy data to user buffer", __func__);
744 ret = -EFAULT;
745 goto exit;
746 }
747 }
748#endif
749#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
750 else if (strncmp(command, "GETBAND", 7) == 0)
751 {
752 int band = -1;
753 char extra[32];
754 tANI_U8 len = 0;
755 hdd_getBand_helper(pHddCtx, &band);
756
757 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
758 if (copy_to_user(priv_data.buf, &extra, len + 1))
759 {
760 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
761 "%s: failed to copy data to user buffer", __func__);
762 ret = -EFAULT;
763 goto exit;
764 }
765 }
766 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
767 {
768 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
769 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
770 tANI_U8 revision = 0;
771 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
772 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
773 char extra[32] = {0};
774 tANI_U8 len = 0;
775
776 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
777 {
778 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
779 "%s: failed to get country code", __func__);
780 ret = -EFAULT;
781 goto exit;
782 }
783 pBuf[uBufLen] = '\0';
784 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
785
786 if (0 == strncmp(pBuf, "KR", 2))
787 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
788 else
789 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
790
791 if (copy_to_user(priv_data.buf, &extra, len + 1))
792 {
793 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
794 "%s: failed to copy data to user buffer", __func__);
795 ret = -EFAULT;
796 goto exit;
797 }
798 }
799 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
800 {
801 tANI_U8 *value = command;
802 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
803 tANI_U8 numChannels = 0;
804 eHalStatus status = eHAL_STATUS_SUCCESS;
805
806 status = hdd_parse_channellist(value, ChannelList, &numChannels);
807 if (eHAL_STATUS_SUCCESS != status)
808 {
809 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
810 "%s: Failed to parse channel list information", __func__);
811 ret = -EINVAL;
812 goto exit;
813 }
814
815 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
816 {
817 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
818 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
819 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
820 ret = -EINVAL;
821 goto exit;
822 }
823 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
824 numChannels);
825 if (eHAL_STATUS_SUCCESS != status)
826 {
827 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
828 "%s: Failed to update channel list information", __func__);
829 ret = -EINVAL;
830 goto exit;
831 }
832 }
833 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
834 {
835 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
836 tANI_U8 numChannels = 0;
837 tANI_U8 len = 0, j = 0;
838 char extra[128] = {0};
839
840 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
841 ChannelList, &numChannels ))
842 {
843 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
844 "%s: failed to get roam scan channel list", __func__);
845 ret = -EFAULT;
846 goto exit;
847 }
848 /* output channel list is of the format
849 [Number of roam scan channels][Channel1][Channel2]... */
850 /* copy the number of channels in the 0th index */
851 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
852 for (j = 0; (j < numChannels); j++)
853 {
854 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
855 }
856
857 if (copy_to_user(priv_data.buf, &extra, len + 1))
858 {
859 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
860 "%s: failed to copy data to user buffer", __func__);
861 ret = -EFAULT;
862 goto exit;
863 }
864 }
865#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700866 else {
867 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
868 __func__, command);
869 }
870
Jeff Johnson295189b2012-06-20 16:38:30 -0700871 }
872exit:
873 if (command)
874 {
875 kfree(command);
876 }
877 return ret;
878}
879
Srinivas Girigowdade697412013-02-14 16:31:48 -0800880#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
881void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
882{
883 eCsrBand band = -1;
884 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
885 switch (band)
886 {
887 case eCSR_BAND_ALL:
888 *pBand = WLAN_HDD_UI_BAND_AUTO;
889 break;
890
891 case eCSR_BAND_24:
892 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
893 break;
894
895 case eCSR_BAND_5G:
896 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
897 break;
898
899 default:
900 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
901 *pBand = -1;
902 break;
903 }
904}
905
906/**---------------------------------------------------------------------------
907
908 \brief hdd_parse_countryrev() - HDD Parse country code revision
909
910 This function parses the country code revision passed in the format
911 SETCOUNTRYREV<space><Country code><space>revision
912
913 \param - pValue Pointer to input country code revision
914 \param - pCountryCode Pointer to local output array to record country code
915 \param - pRevision Pointer to store revision integer number
916
917 \return - 0 for success non-zero for failure
918
919 --------------------------------------------------------------------------*/
920VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
921{
922 tANI_U8 *inPtr = pValue;
923 int tempInt;
924
925 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
926 /*no argument after the command*/
927 if (NULL == inPtr)
928 {
929 return -EINVAL;
930 }
931
932 /*no space after the command*/
933 else if (SPACE_ASCII_VALUE != *inPtr)
934 {
935 return -EINVAL;
936 }
937
938 /*removing empty spaces*/
939 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
940
941 /*no argument followed by spaces*/
942 if ('\0' == *inPtr)
943 {
944 return -EINVAL;
945 }
946
947 /*getting the first argument ie the country code */
948 sscanf(inPtr, "%s ", pCountryCode);
949
950 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
951 "Country code is : %s", pCountryCode);
952
953 /*inPtr pointing to the beginning of first space after country code */
954 inPtr = strpbrk( inPtr, " " );
955 /*no revision number after the country code argument */
956 if (NULL == inPtr)
957 {
958 return -EINVAL;
959 }
960
961 inPtr++;
962
963 /*removing empty space*/
964 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
965
966 /*no channel list after the number of channels argument and spaces*/
967 if (0 == strncmp(pCountryCode, "KR", 2))
968 {
969 if ('\0' == *inPtr)
970 {
971 return -EINVAL;
972 }
973
974 sscanf(inPtr, "%d", &tempInt);
975 *pRevision = tempInt;
976 }
977 else
978 {
979 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
980 "Revision input is required only for Country KR");
981 return -EINVAL;
982 }
983 return VOS_STATUS_SUCCESS;
984}
985
986/**---------------------------------------------------------------------------
987
988 \brief hdd_parse_channellist() - HDD Parse channel list
989
990 This function parses the channel list passed in the format
991 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
992
993 \param - pValue Pointer to input channel list
994 \param - ChannelList Pointer to local output array to record channel list
995 \param - pNumChannels Pointer to number of roam scan channels
996
997 \return - 0 for success non-zero for failure
998
999 --------------------------------------------------------------------------*/
1000VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
1001{
1002 tANI_U8 *inPtr = pValue;
1003 int tempInt;
1004 int j = 0;
1005 int v = 0;
1006 char buf[32];
1007
1008 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1009 /*no argument after the command*/
1010 if (NULL == inPtr)
1011 {
1012 return -EINVAL;
1013 }
1014
1015 /*no space after the command*/
1016 else if (SPACE_ASCII_VALUE != *inPtr)
1017 {
1018 return -EINVAL;
1019 }
1020
1021 /*removing empty spaces*/
1022 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
1023
1024 /*no argument followed by spaces*/
1025 if ('\0' == *inPtr)
1026 {
1027 return -EINVAL;
1028 }
1029
1030 /*getting the first argument ie the number of channels*/
1031 sscanf(inPtr, "%s ", buf);
1032 v = kstrtos32(buf, 10, &tempInt);
1033 if ( v < 0) return -EINVAL;
1034
1035 *pNumChannels = tempInt;
1036
1037 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1038 "Number of channels are: %d", *pNumChannels);
1039
1040 for (j = 0; j < (*pNumChannels); j++)
1041 {
1042 /*inPtr pointing to the beginning of first space after number of channels*/
1043 inPtr = strpbrk( inPtr, " " );
1044 /*no channel list after the number of channels argument*/
1045 if (NULL == inPtr)
1046 {
1047 return -EINVAL;
1048 }
1049
1050 /*removing empty space*/
1051 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1052
1053 /*no channel list after the number of channels argument and spaces*/
1054 if ( '\0' == *inPtr )
1055 {
1056 return -EINVAL;
1057 }
1058
1059 sscanf(inPtr, "%s ", buf);
1060 v = kstrtos32(buf, 10, &tempInt);
1061 if ( v < 0) return -EINVAL;
1062 pChannelList[j] = tempInt;
1063
1064 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1065 "Channel %d added to preferred channel list",
1066 pChannelList[j] );
1067 }
1068
1069 /* if the actual number of channels passed are more than
1070 pNumChannels then ignore the rest; take only pNumChannels */
1071 return VOS_STATUS_SUCCESS;
1072}
1073
1074#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001075/**---------------------------------------------------------------------------
1076
1077 \brief hdd_open() - HDD Open function
1078
1079 This is called in response to ifconfig up
1080
1081 \param - dev Pointer to net_device structure
1082
1083 \return - 0 for success non-zero for failure
1084
1085 --------------------------------------------------------------------------*/
1086int hdd_open (struct net_device *dev)
1087{
1088 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1089 hdd_context_t *pHddCtx;
1090 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1091 VOS_STATUS status;
1092 v_BOOL_t in_standby = TRUE;
1093
1094 if (NULL == pAdapter)
1095 {
1096 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001097 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001098 return -ENODEV;
1099 }
1100
1101 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1102 if (NULL == pHddCtx)
1103 {
1104 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001105 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001106 return -ENODEV;
1107 }
1108
1109 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1110 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1111 {
1112 if( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
1113 {
1114 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of "
1115 "standby", __func__, pAdapter->device_mode);
1116 in_standby = FALSE;
1117 break;
1118 }
1119 else
1120 {
1121 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1122 pAdapterNode = pNext;
1123 }
1124 }
1125
1126 if (TRUE == in_standby)
1127 {
1128 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
1129 {
1130 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
1131 "wlan out of power save", __func__);
1132 return -EINVAL;
1133 }
1134 }
1135
1136 pAdapter->event_flags |= DEVICE_IFACE_OPENED;
1137 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
1138 {
1139 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001140 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001141 /* Enable TX queues only when we are connected */
1142 netif_tx_start_all_queues(dev);
1143 }
1144
1145 return 0;
1146}
1147
1148int hdd_mon_open (struct net_device *dev)
1149{
1150 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1151
1152 if(pAdapter == NULL) {
1153 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001154 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001155 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001156 }
1157
1158 netif_start_queue(dev);
1159
1160 return 0;
1161}
1162/**---------------------------------------------------------------------------
1163
1164 \brief hdd_stop() - HDD stop function
1165
1166 This is called in response to ifconfig down
1167
1168 \param - dev Pointer to net_device structure
1169
1170 \return - 0 for success non-zero for failure
1171
1172 --------------------------------------------------------------------------*/
1173
1174int hdd_stop (struct net_device *dev)
1175{
1176 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1177 hdd_context_t *pHddCtx;
1178 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1179 VOS_STATUS status;
1180 v_BOOL_t enter_standby = TRUE;
1181
1182 ENTER();
1183
1184 if (NULL == pAdapter)
1185 {
1186 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001187 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001188 return -ENODEV;
1189 }
1190
1191 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1192 if (NULL == pHddCtx)
1193 {
1194 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001195 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001196 return -ENODEV;
1197 }
1198
1199 pAdapter->event_flags &= ~(DEVICE_IFACE_OPENED);
1200 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
1201 netif_tx_disable(pAdapter->dev);
1202 netif_carrier_off(pAdapter->dev);
1203
1204
1205 /* SoftAP ifaces should never go in power save mode
1206 making sure same here. */
1207 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
1208 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
1209#ifdef WLAN_FEATURE_P2P
1210 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
1211#endif
1212 )
1213 {
1214 /* SoftAP mode, so return from here */
1215 EXIT();
1216 return 0;
1217 }
1218
1219 /* Find if any iface is up then
1220 if any iface is up then can't put device to sleep/ power save mode. */
1221 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1222 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1223 {
1224 if ( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
1225 {
1226 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
1227 "put device to sleep", __func__, pAdapter->device_mode);
1228 enter_standby = FALSE;
1229 break;
1230 }
1231 else
1232 {
1233 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1234 pAdapterNode = pNext;
1235 }
1236 }
1237
1238 if (TRUE == enter_standby)
1239 {
1240 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
1241 "entering standby", __func__);
1242 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
1243 {
1244 /*log and return success*/
1245 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
1246 "wlan in power save", __func__);
1247 }
1248 }
1249
1250 EXIT();
1251 return 0;
1252}
1253
1254/**---------------------------------------------------------------------------
1255
1256 \brief hdd_uninit() - HDD uninit function
1257
1258 This is called during the netdev unregister to uninitialize all data
1259associated with the device
1260
1261 \param - dev Pointer to net_device structure
1262
1263 \return - void
1264
1265 --------------------------------------------------------------------------*/
1266static void hdd_uninit (struct net_device *dev)
1267{
1268 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1269
1270 ENTER();
1271
1272 do
1273 {
1274 if (NULL == pAdapter)
1275 {
1276 hddLog(VOS_TRACE_LEVEL_FATAL,
1277 "%s: NULL pAdapter", __func__);
1278 break;
1279 }
1280
1281 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1282 {
1283 hddLog(VOS_TRACE_LEVEL_FATAL,
1284 "%s: Invalid magic", __func__);
1285 break;
1286 }
1287
1288 if (NULL == pAdapter->pHddCtx)
1289 {
1290 hddLog(VOS_TRACE_LEVEL_FATAL,
1291 "%s: NULL pHddCtx", __func__);
1292 break;
1293 }
1294
1295 if (dev != pAdapter->dev)
1296 {
1297 hddLog(VOS_TRACE_LEVEL_FATAL,
1298 "%s: Invalid device reference", __func__);
1299 /* we haven't validated all cases so let this go for now */
1300 }
1301
1302 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
1303
1304 /* after uninit our adapter structure will no longer be valid */
1305 pAdapter->dev = NULL;
1306 pAdapter->magic = 0;
1307 } while (0);
1308
1309 EXIT();
1310}
1311
1312/**---------------------------------------------------------------------------
1313
1314 \brief hdd_release_firmware() -
1315
1316 This function calls the release firmware API to free the firmware buffer.
1317
1318 \param - pFileName Pointer to the File Name.
1319 pCtx - Pointer to the adapter .
1320
1321
1322 \return - 0 for success, non zero for failure
1323
1324 --------------------------------------------------------------------------*/
1325
1326VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
1327{
1328 VOS_STATUS status = VOS_STATUS_SUCCESS;
1329 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1330 ENTER();
1331
1332
1333 if (!strcmp(WLAN_FW_FILE, pFileName)) {
1334
1335 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
1336
1337 if(pHddCtx->fw) {
1338 release_firmware(pHddCtx->fw);
1339 pHddCtx->fw = NULL;
1340 }
1341 else
1342 status = VOS_STATUS_E_FAILURE;
1343 }
1344 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
1345 if(pHddCtx->nv) {
1346 release_firmware(pHddCtx->nv);
1347 pHddCtx->nv = NULL;
1348 }
1349 else
1350 status = VOS_STATUS_E_FAILURE;
1351
1352 }
1353
1354 EXIT();
1355 return status;
1356}
1357
1358/**---------------------------------------------------------------------------
1359
1360 \brief hdd_request_firmware() -
1361
1362 This function reads the firmware file using the request firmware
1363 API and returns the the firmware data and the firmware file size.
1364
1365 \param - pfileName - Pointer to the file name.
1366 - pCtx - Pointer to the adapter .
1367 - ppfw_data - Pointer to the pointer of the firmware data.
1368 - pSize - Pointer to the file size.
1369
1370 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
1371
1372 --------------------------------------------------------------------------*/
1373
1374
1375VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
1376{
1377 int status;
1378 VOS_STATUS retval = VOS_STATUS_SUCCESS;
1379 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1380 ENTER();
1381
1382 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
1383
1384 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
1385
1386 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1387 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
1388 __func__, pfileName);
1389 retval = VOS_STATUS_E_FAILURE;
1390 }
1391
1392 else {
1393 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
1394 *pSize = pHddCtx->fw->size;
1395 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
1396 __func__, *pSize);
1397 }
1398 }
1399 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
1400
1401 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
1402
1403 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
1404 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
1405 __func__, pfileName);
1406 retval = VOS_STATUS_E_FAILURE;
1407 }
1408
1409 else {
1410 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
1411 *pSize = pHddCtx->nv->size;
1412 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
1413 __func__, *pSize);
1414 }
1415 }
1416
1417 EXIT();
1418 return retval;
1419}
1420/**---------------------------------------------------------------------------
1421 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
1422
1423 This is the function invoked by SME to inform the result of a full power
1424 request issued by HDD
1425
1426 \param - callbackcontext - Pointer to cookie
1427 status - result of request
1428
1429 \return - None
1430
1431--------------------------------------------------------------------------*/
1432void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
1433{
1434 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
1435
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001436 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001437 if(&pHddCtx->full_pwr_comp_var)
1438 {
1439 complete(&pHddCtx->full_pwr_comp_var);
1440 }
1441}
1442
1443/**---------------------------------------------------------------------------
1444
1445 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
1446
1447 This is the function invoked by SME to inform the result of BMPS
1448 request issued by HDD
1449
1450 \param - callbackcontext - Pointer to cookie
1451 status - result of request
1452
1453 \return - None
1454
1455--------------------------------------------------------------------------*/
1456void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
1457{
1458
1459 struct completion *completion_var = (struct completion*) callbackContext;
1460
1461 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
1462 if(completion_var != NULL)
1463 {
1464 complete(completion_var);
1465 }
1466}
1467
1468/**---------------------------------------------------------------------------
1469
1470 \brief hdd_get_cfg_file_size() -
1471
1472 This function reads the configuration file using the request firmware
1473 API and returns the configuration file size.
1474
1475 \param - pCtx - Pointer to the adapter .
1476 - pFileName - Pointer to the file name.
1477 - pBufSize - Pointer to the buffer size.
1478
1479 \return - 0 for success, non zero for failure
1480
1481 --------------------------------------------------------------------------*/
1482
1483VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
1484{
1485 int status;
1486 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1487
1488 ENTER();
1489
1490 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
1491
1492 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1493 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
1494 status = VOS_STATUS_E_FAILURE;
1495 }
1496 else {
1497 *pBufSize = pHddCtx->fw->size;
1498 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
1499 release_firmware(pHddCtx->fw);
1500 pHddCtx->fw = NULL;
1501 }
1502
1503 EXIT();
1504 return VOS_STATUS_SUCCESS;
1505}
1506
1507/**---------------------------------------------------------------------------
1508
1509 \brief hdd_read_cfg_file() -
1510
1511 This function reads the configuration file using the request firmware
1512 API and returns the cfg data and the buffer size of the configuration file.
1513
1514 \param - pCtx - Pointer to the adapter .
1515 - pFileName - Pointer to the file name.
1516 - pBuffer - Pointer to the data buffer.
1517 - pBufSize - Pointer to the buffer size.
1518
1519 \return - 0 for success, non zero for failure
1520
1521 --------------------------------------------------------------------------*/
1522
1523VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
1524 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
1525{
1526 int status;
1527 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1528
1529 ENTER();
1530
1531 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
1532
1533 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1534 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
1535 return VOS_STATUS_E_FAILURE;
1536 }
1537 else {
1538 if(*pBufSize != pHddCtx->fw->size) {
1539 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
1540 "file size", __func__);
1541 release_firmware(pHddCtx->fw);
1542 pHddCtx->fw = NULL;
1543 return VOS_STATUS_E_FAILURE;
1544 }
1545 else {
1546 if(pBuffer) {
1547 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
1548 }
1549 release_firmware(pHddCtx->fw);
1550 pHddCtx->fw = NULL;
1551 }
1552 }
1553
1554 EXIT();
1555
1556 return VOS_STATUS_SUCCESS;
1557}
1558
1559/**---------------------------------------------------------------------------
1560
1561 \brief hdd_set_mac_addr_cb() -
1562
1563 This function is the call back function for setting the station
1564 mac adrress called by ccm module to indicate the
1565 success/failure result.
1566
1567 \param - hHal - Pointer to the hal module.
1568 - result - returns the result of the set mac address.
1569
1570 \return - void
1571
1572 --------------------------------------------------------------------------*/
1573#ifndef FEATURE_WLAN_INTEGRATED_SOC
1574static void hdd_set_mac_addr_cb( tHalHandle hHal, tANI_S32 result )
1575{
1576 // ignore the STA_ID response for now.
1577
1578 VOS_ASSERT( CCM_IS_RESULT_SUCCESS( result ) );
1579}
1580#endif
1581
1582
1583/**---------------------------------------------------------------------------
1584
1585 \brief hdd_set_mac_address() -
1586
1587 This function sets the user specified mac address using
1588 the command ifconfig wlanX hw ether <mac adress>.
1589
1590 \param - dev - Pointer to the net device.
1591 - addr - Pointer to the sockaddr.
1592 \return - 0 for success, non zero for failure
1593
1594 --------------------------------------------------------------------------*/
1595
1596static int hdd_set_mac_address(struct net_device *dev, void *addr)
1597{
1598 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1599 struct sockaddr *psta_mac_addr = addr;
1600 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1601
1602 ENTER();
1603
1604 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
1605
1606#ifdef HDD_SESSIONIZE
1607 // set the MAC address though the STA ID CFG.
1608 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
1609 (v_U8_t *)&pAdapter->macAddressCurrent,
1610 sizeof( pAdapter->macAddressCurrent ),
1611 hdd_set_mac_addr_cb, VOS_FALSE );
1612#endif
1613
1614 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
1615
1616 EXIT();
1617 return halStatus;
1618}
1619
1620tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
1621{
1622 int i;
1623 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
1624 {
1625 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
1626 break;
1627 }
1628
1629 if( VOS_MAX_CONCURRENCY_PERSONA == i)
1630 return NULL;
1631
1632 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
1633 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
1634}
1635
1636void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
1637{
1638 int i;
1639 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
1640 {
1641 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
1642 {
1643 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
1644 break;
1645 }
1646 }
1647 return;
1648}
1649
1650#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1651 static struct net_device_ops wlan_drv_ops = {
1652 .ndo_open = hdd_open,
1653 .ndo_stop = hdd_stop,
1654 .ndo_uninit = hdd_uninit,
1655 .ndo_start_xmit = hdd_hard_start_xmit,
1656 .ndo_tx_timeout = hdd_tx_timeout,
1657 .ndo_get_stats = hdd_stats,
1658 .ndo_do_ioctl = hdd_ioctl,
1659 .ndo_set_mac_address = hdd_set_mac_address,
1660 .ndo_select_queue = hdd_select_queue,
1661#ifdef WLAN_FEATURE_PACKET_FILTERING
1662#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
1663 .ndo_set_rx_mode = hdd_set_multicast_list,
1664#else
1665 .ndo_set_multicast_list = hdd_set_multicast_list,
1666#endif //LINUX_VERSION_CODE
1667#endif
1668 };
1669#ifdef CONFIG_CFG80211
1670 static struct net_device_ops wlan_mon_drv_ops = {
1671 .ndo_open = hdd_mon_open,
1672 .ndo_stop = hdd_stop,
1673 .ndo_uninit = hdd_uninit,
1674 .ndo_start_xmit = hdd_mon_hard_start_xmit,
1675 .ndo_tx_timeout = hdd_tx_timeout,
1676 .ndo_get_stats = hdd_stats,
1677 .ndo_do_ioctl = hdd_ioctl,
1678 .ndo_set_mac_address = hdd_set_mac_address,
1679 };
1680#endif
1681
1682#endif
1683
1684void hdd_set_station_ops( struct net_device *pWlanDev )
1685{
1686#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1687 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
1688 pWlanDev->netdev_ops = &wlan_drv_ops;
1689#else
1690 pWlanDev->open = hdd_open;
1691 pWlanDev->stop = hdd_stop;
1692 pWlanDev->uninit = hdd_uninit;
1693 pWlanDev->hard_start_xmit = NULL;
1694 pWlanDev->tx_timeout = hdd_tx_timeout;
1695 pWlanDev->get_stats = hdd_stats;
1696 pWlanDev->do_ioctl = hdd_ioctl;
1697 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
1698 pWlanDev->set_mac_address = hdd_set_mac_address;
1699#endif
1700}
1701
Jeff Johnsoneed415b2013-01-18 16:11:20 -08001702static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07001703{
1704 struct net_device *pWlanDev = NULL;
1705 hdd_adapter_t *pAdapter = NULL;
1706#ifdef CONFIG_CFG80211
1707 /*
1708 * cfg80211 initialization and registration....
1709 */
1710 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
1711
1712#else
1713 //Allocate the net_device and private data (station ctx)
1714 pWlanDev = alloc_etherdev_mq(sizeof( hdd_adapter_t ), NUM_TX_QUEUES);
1715
1716#endif
1717
1718 if(pWlanDev != NULL)
1719 {
1720
1721 //Save the pointer to the net_device in the HDD adapter
1722 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
1723
1724#ifndef CONFIG_CFG80211
1725 //Init the net_device structure
1726 ether_setup(pWlanDev);
1727#endif
1728
1729 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
1730
1731 pAdapter->dev = pWlanDev;
1732 pAdapter->pHddCtx = pHddCtx;
1733 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
1734
1735 init_completion(&pAdapter->session_open_comp_var);
1736 init_completion(&pAdapter->session_close_comp_var);
1737 init_completion(&pAdapter->disconnect_comp_var);
1738 init_completion(&pAdapter->linkup_event_var);
1739 init_completion(&pAdapter->cancel_rem_on_chan_var);
1740 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001741#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1742 init_completion(&pAdapter->offchannel_tx_event);
1743#endif
1744#ifdef CONFIG_CFG80211
1745 init_completion(&pAdapter->tx_action_cnf_event);
1746#endif
Hoonki Lee11f7dda2013-02-14 16:55:44 -08001747#ifdef FEATURE_WLAN_TDLS
1748 init_completion(&pAdapter->tdls_add_station_comp);
1749#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001750 init_completion(&pHddCtx->mc_sus_event_var);
1751 init_completion(&pHddCtx->tx_sus_event_var);
1752
Jeff Johnson295189b2012-06-20 16:38:30 -07001753 pAdapter->isLinkUpSvcNeeded = FALSE;
1754 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
1755 //Init the net_device structure
1756 strlcpy(pWlanDev->name, name, IFNAMSIZ);
1757
1758 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
1759 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
1760 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
1761 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
1762
1763 hdd_set_station_ops( pAdapter->dev );
1764
1765 pWlanDev->destructor = free_netdev;
1766#ifdef CONFIG_CFG80211
1767 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
1768 pAdapter->wdev.wiphy = pHddCtx->wiphy;
1769 pAdapter->wdev.netdev = pWlanDev;
1770#endif
1771 /* set pWlanDev's parent to underlying device */
1772 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
1773 }
1774
1775 return pAdapter;
1776}
1777
1778VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
1779{
1780 struct net_device *pWlanDev = pAdapter->dev;
1781 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1782 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1783 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1784
1785 if( rtnl_lock_held )
1786 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001787 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07001788 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
1789 {
1790 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
1791 return VOS_STATUS_E_FAILURE;
1792 }
1793 }
1794 if (register_netdevice(pWlanDev))
1795 {
1796 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
1797 return VOS_STATUS_E_FAILURE;
1798 }
1799 }
1800 else
1801 {
1802 if(register_netdev(pWlanDev))
1803 {
1804 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
1805 return VOS_STATUS_E_FAILURE;
1806 }
1807 }
1808 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
1809
1810 return VOS_STATUS_SUCCESS;
1811}
1812
1813eHalStatus hdd_smeCloseSessionCallback(void *pContext)
1814{
1815 if(pContext != NULL)
1816 {
1817 clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags);
1818
1819 /* need to make sure all of our scheduled work has completed.
1820 * This callback is called from MC thread context, so it is safe to
1821 * to call below flush workqueue API from here.
1822 */
1823 flush_scheduled_work();
1824 complete(&((hdd_adapter_t*)pContext)->session_close_comp_var);
1825 }
1826 return eHAL_STATUS_SUCCESS;
1827}
1828
1829VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
1830{
1831 struct net_device *pWlanDev = pAdapter->dev;
1832 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1833 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1834 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1835 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1836 int rc = 0;
1837
1838 INIT_COMPLETION(pAdapter->session_open_comp_var);
1839 //Open a SME session for future operation
1840 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
1841 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
1842 if ( !HAL_STATUS_SUCCESS( halStatus ) )
1843 {
1844 hddLog(VOS_TRACE_LEVEL_FATAL,
1845 "sme_OpenSession() failed with status code %08d [x%08lx]",
1846 halStatus, halStatus );
1847 status = VOS_STATUS_E_FAILURE;
1848 goto error_sme_open;
1849 }
1850
1851 //Block on a completion variable. Can't wait forever though.
1852 rc = wait_for_completion_interruptible_timeout(
1853 &pAdapter->session_open_comp_var,
1854 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1855 if (!rc)
1856 {
1857 hddLog(VOS_TRACE_LEVEL_FATAL,
1858 "Session is not opened within timeout period code %08d", rc );
1859 status = VOS_STATUS_E_FAILURE;
1860 goto error_sme_open;
1861 }
1862
1863 // Register wireless extensions
1864 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
1865 {
1866 hddLog(VOS_TRACE_LEVEL_FATAL,
1867 "hdd_register_wext() failed with status code %08d [x%08lx]",
1868 halStatus, halStatus );
1869 status = VOS_STATUS_E_FAILURE;
1870 goto error_register_wext;
1871 }
1872 //Safe to register the hard_start_xmit function again
1873#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1874 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
1875#else
1876 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
1877#endif
1878
1879 //Set the Connection State to Not Connected
1880 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
1881
1882 //Set the default operation channel
1883 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
1884
1885 /* Make the default Auth Type as OPEN*/
1886 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
1887
1888 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
1889 {
1890 hddLog(VOS_TRACE_LEVEL_FATAL,
1891 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
1892 status, status );
1893 goto error_init_txrx;
1894 }
1895
1896 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1897
1898 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
1899 {
1900 hddLog(VOS_TRACE_LEVEL_FATAL,
1901 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
1902 status, status );
1903 goto error_wmm_init;
1904 }
1905
1906 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1907
1908 return VOS_STATUS_SUCCESS;
1909
1910error_wmm_init:
1911 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1912 hdd_deinit_tx_rx(pAdapter);
1913error_init_txrx:
1914 hdd_UnregisterWext(pWlanDev);
1915error_register_wext:
1916 if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
1917 {
1918 INIT_COMPLETION(pAdapter->session_close_comp_var);
1919 if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
1920 pAdapter->sessionId,
1921 hdd_smeCloseSessionCallback, pAdapter ) )
1922 {
1923 //Block on a completion variable. Can't wait forever though.
1924 wait_for_completion_interruptible_timeout(
1925 &pAdapter->session_close_comp_var,
1926 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1927 }
1928}
1929error_sme_open:
1930 return status;
1931}
1932
Jeff Johnson295189b2012-06-20 16:38:30 -07001933#ifdef CONFIG_CFG80211
1934void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1935{
1936 hdd_cfg80211_state_t *cfgState;
1937
1938 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1939
1940 if( NULL != cfgState->buf )
1941 {
1942 int rc;
1943 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
1944 rc = wait_for_completion_interruptible_timeout(
1945 &pAdapter->tx_action_cnf_event,
1946 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
1947 if(!rc)
1948 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08001949 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001950 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
1951 }
1952 }
1953 return;
1954}
1955#endif
1956
1957void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1958{
1959 ENTER();
1960 switch ( pAdapter->device_mode )
1961 {
1962 case WLAN_HDD_INFRA_STATION:
1963 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07001964 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07001965 {
1966 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1967 {
1968 hdd_deinit_tx_rx( pAdapter );
1969 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1970 }
1971
1972 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
1973 {
1974 hdd_wmm_adapter_close( pAdapter );
1975 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1976 }
1977
1978#ifdef CONFIG_CFG80211
1979 hdd_cleanup_actionframe(pHddCtx, pAdapter);
1980#endif
1981
1982 break;
1983 }
1984
1985 case WLAN_HDD_SOFTAP:
1986 case WLAN_HDD_P2P_GO:
1987#ifdef WLAN_SOFTAP_FEATURE
1988 {
1989#ifdef CONFIG_CFG80211
1990 hdd_cleanup_actionframe(pHddCtx, pAdapter);
1991#endif
1992
1993 hdd_unregister_hostapd(pAdapter);
1994 hdd_set_conparam( 0 );
1995#ifdef CONFIG_CFG80211
1996 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
1997#endif
1998 break;
1999 }
2000
2001 case WLAN_HDD_MONITOR:
2002 {
2003#ifdef CONFIG_CFG80211
2004 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
2005#endif
2006 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2007 {
2008 hdd_deinit_tx_rx( pAdapter );
2009 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2010 }
2011#ifdef CONFIG_CFG80211
2012 if(NULL != pAdapterforTx)
2013 {
2014 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
2015 }
2016#endif
2017#endif //WLAN_SOFTAP_FEATURE
2018 break;
2019 }
2020
2021
2022 default:
2023 break;
2024 }
2025
2026 EXIT();
2027}
2028
2029void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
2030{
2031 struct net_device *pWlanDev = pAdapter->dev;
2032
2033 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
2034 if( rtnl_held )
2035 {
2036 unregister_netdevice(pWlanDev);
2037 }
2038 else
2039 {
2040 unregister_netdev(pWlanDev);
2041 }
2042 // note that the pAdapter is no longer valid at this point
2043 // since the memory has been reclaimed
2044 }
2045
2046}
2047
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08002048void hdd_set_pwrparams(hdd_context_t *pHddCtx)
2049{
2050 tSirSetPowerParamsReq powerRequest = { 0 };
2051
2052 powerRequest.uIgnoreDTIM = 1;
2053
2054 if (pHddCtx->cfg_ini->enableModulatedDTIM)
2055 {
2056 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
2057 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2058 }
2059 else
2060 {
2061 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
2062 }
2063
2064 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
2065 *specified during Enter/Exit BMPS when LCD off*/
2066 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2067 NULL, eANI_BOOLEAN_FALSE);
2068 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2069 NULL, eANI_BOOLEAN_FALSE);
2070
2071 /* switch to the DTIM specified in cfg.ini */
2072 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2073 "Switch to DTIM%d", powerRequest.uListenInterval);
2074 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2075
2076}
2077
2078void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
2079{
2080 /*Switch back to DTIM 1*/
2081 tSirSetPowerParamsReq powerRequest = { 0 };
2082
2083 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
2084 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2085
2086 /* Update ignoreDTIM and ListedInterval in CFG with default values */
2087 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2088 NULL, eANI_BOOLEAN_FALSE);
2089 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2090 NULL, eANI_BOOLEAN_FALSE);
2091
2092 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2093 "Switch to DTIM%d",powerRequest.uListenInterval);
2094 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2095
2096}
2097
Jeff Johnson295189b2012-06-20 16:38:30 -07002098VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
2099{
2100 VOS_STATUS status = VOS_STATUS_SUCCESS;
2101
2102 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2103 {
2104 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2105 }
2106
2107 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2108 {
2109 sme_StartAutoBmpsTimer(pHddCtx->hHal);
2110 }
2111
2112 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2113 {
2114 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2115 }
2116
2117 return status;
2118}
2119
2120VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
2121{
2122 hdd_adapter_t *pAdapter = NULL;
2123 eHalStatus halStatus;
2124 VOS_STATUS status = VOS_STATUS_E_INVAL;
2125 v_BOOL_t disableBmps = FALSE;
2126 v_BOOL_t disableImps = FALSE;
2127
2128 switch(session_type)
2129 {
2130 case WLAN_HDD_INFRA_STATION:
2131 case WLAN_HDD_SOFTAP:
2132#ifdef WLAN_FEATURE_P2P
2133 case WLAN_HDD_P2P_CLIENT:
2134 case WLAN_HDD_P2P_GO:
2135#endif
2136 //Exit BMPS -> Is Sta/P2P Client is already connected
2137 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
2138 if((NULL != pAdapter)&&
2139 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2140 {
2141 disableBmps = TRUE;
2142 }
2143
2144 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
2145 if((NULL != pAdapter)&&
2146 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2147 {
2148 disableBmps = TRUE;
2149 }
2150
2151 //Exit both Bmps and Imps incase of Go/SAP Mode
2152 if((WLAN_HDD_SOFTAP == session_type) ||
2153 (WLAN_HDD_P2P_GO == session_type))
2154 {
2155 disableBmps = TRUE;
2156 disableImps = TRUE;
2157 }
2158
2159 if(TRUE == disableImps)
2160 {
2161 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2162 {
2163 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2164 }
2165 }
2166
2167 if(TRUE == disableBmps)
2168 {
2169 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2170 {
2171 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2172
2173 if(eHAL_STATUS_SUCCESS != halStatus)
2174 {
2175 status = VOS_STATUS_E_FAILURE;
2176 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
2177 VOS_ASSERT(0);
2178 return status;
2179 }
2180 }
2181
2182 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2183 {
2184 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
2185
2186 if(eHAL_STATUS_SUCCESS != halStatus)
2187 {
2188 status = VOS_STATUS_E_FAILURE;
2189 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
2190 VOS_ASSERT(0);
2191 return status;
2192 }
2193 }
2194 }
2195
2196 if((TRUE == disableBmps) ||
2197 (TRUE == disableImps))
2198 {
2199 /* Now, get the chip into Full Power now */
2200 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
2201 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
2202 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
2203
2204 if(halStatus != eHAL_STATUS_SUCCESS)
2205 {
2206 if(halStatus == eHAL_STATUS_PMC_PENDING)
2207 {
2208 //Block on a completion variable. Can't wait forever though
2209 wait_for_completion_interruptible_timeout(
2210 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
2211 }
2212 else
2213 {
2214 status = VOS_STATUS_E_FAILURE;
2215 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
2216 VOS_ASSERT(0);
2217 return status;
2218 }
2219 }
2220
2221 status = VOS_STATUS_SUCCESS;
2222 }
2223
2224 break;
2225 }
2226 return status;
2227}
2228
2229hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002230 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07002231 tANI_U8 rtnl_held )
2232{
2233 hdd_adapter_t *pAdapter = NULL;
2234 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
2235 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2236 VOS_STATUS exitbmpsStatus;
2237
2238 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
2239
2240 //Disable BMPS incase of Concurrency
2241 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
2242
2243 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
2244 {
2245 //Fail to Exit BMPS
2246 VOS_ASSERT(0);
2247 return NULL;
2248 }
2249
2250 switch(session_type)
2251 {
2252 case WLAN_HDD_INFRA_STATION:
2253#ifdef WLAN_FEATURE_P2P
2254 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002255 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002256#endif
2257 {
2258 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2259
2260 if( NULL == pAdapter )
2261 return NULL;
2262
2263#ifdef CONFIG_CFG80211
Jeff Johnsone7245742012-09-05 17:12:55 -07002264 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
2265 NL80211_IFTYPE_P2P_CLIENT:
2266 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07002267#endif
2268
Jeff Johnson295189b2012-06-20 16:38:30 -07002269 pAdapter->device_mode = session_type;
2270
2271 status = hdd_init_station_mode( pAdapter );
2272 if( VOS_STATUS_SUCCESS != status )
2273 goto err_free_netdev;
2274
2275 status = hdd_register_interface( pAdapter, rtnl_held );
2276 if( VOS_STATUS_SUCCESS != status )
2277 {
2278 hdd_deinit_adapter(pHddCtx, pAdapter);
2279 goto err_free_netdev;
2280 }
2281 //Stop the Interface TX queue.
2282 netif_tx_disable(pAdapter->dev);
2283 //netif_tx_disable(pWlanDev);
2284 netif_carrier_off(pAdapter->dev);
2285
2286 break;
2287 }
2288
2289#ifdef WLAN_FEATURE_P2P
2290 case WLAN_HDD_P2P_GO:
2291#endif
2292 case WLAN_HDD_SOFTAP:
2293 {
2294 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
2295 if( NULL == pAdapter )
2296 return NULL;
2297
2298#ifdef CONFIG_CFG80211
2299 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
2300 NL80211_IFTYPE_AP:
2301 NL80211_IFTYPE_P2P_GO;
2302#endif
2303 pAdapter->device_mode = session_type;
2304
2305 status = hdd_init_ap_mode(pAdapter);
2306 if( VOS_STATUS_SUCCESS != status )
2307 goto err_free_netdev;
2308
2309 status = hdd_register_hostapd( pAdapter, rtnl_held );
2310 if( VOS_STATUS_SUCCESS != status )
2311 {
2312 hdd_deinit_adapter(pHddCtx, pAdapter);
2313 goto err_free_netdev;
2314 }
2315
2316 netif_tx_disable(pAdapter->dev);
2317 netif_carrier_off(pAdapter->dev);
2318
2319 hdd_set_conparam( 1 );
2320 break;
2321 }
2322 case WLAN_HDD_MONITOR:
2323 {
2324#ifdef CONFIG_CFG80211
2325 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2326 if( NULL == pAdapter )
2327 return NULL;
2328
2329 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
2330 pAdapter->device_mode = session_type;
2331 status = hdd_register_interface( pAdapter, rtnl_held );
2332#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
2333 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
2334#else
2335 pAdapter->dev->open = hdd_mon_open;
2336 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
2337#endif
2338 hdd_init_tx_rx( pAdapter );
2339 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2340 //Set adapter to be used for data tx. It will use either GO or softap.
2341 pAdapter->sessionCtx.monitor.pAdapterForTx =
2342 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
2343#ifdef WLAN_FEATURE_P2P
2344 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
2345 {
2346 pAdapter->sessionCtx.monitor.pAdapterForTx =
2347 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
2348 }
2349#endif
2350 /* This workqueue will be used to transmit management packet over
2351 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07002352 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
2353 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
2354 return NULL;
2355 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07002356
Jeff Johnson295189b2012-06-20 16:38:30 -07002357 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
2358 hdd_mon_tx_work_queue);
2359#endif
2360 }
2361 break;
2362#ifdef ANI_MANF_DIAG
2363 case WLAN_HDD_FTM:
2364 {
2365 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2366
2367 if( NULL == pAdapter )
2368 return NULL;
2369 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
2370 * message while loading driver in FTM mode. */
2371 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
2372 pAdapter->device_mode = session_type;
2373 status = hdd_register_interface( pAdapter, rtnl_held );
2374 }
2375 break;
2376#endif
2377 default:
2378 {
2379 VOS_ASSERT(0);
2380 return NULL;
2381 }
2382 }
2383
2384
2385 if( VOS_STATUS_SUCCESS == status )
2386 {
2387 //Add it to the hdd's session list.
2388 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
2389 if( NULL == pHddAdapterNode )
2390 {
2391 status = VOS_STATUS_E_NOMEM;
2392 }
2393 else
2394 {
2395 pHddAdapterNode->pAdapter = pAdapter;
2396 status = hdd_add_adapter_back ( pHddCtx,
2397 pHddAdapterNode );
2398 }
2399 }
2400
2401 if( VOS_STATUS_SUCCESS != status )
2402 {
2403 if( NULL != pAdapter )
2404 {
2405 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
2406 pAdapter = NULL;
2407 }
2408 if( NULL != pHddAdapterNode )
2409 {
2410 vos_mem_free( pHddAdapterNode );
2411 }
2412
2413 goto resume_bmps;
2414 }
2415
2416 if(VOS_STATUS_SUCCESS == status)
2417 {
2418 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
2419
2420#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
2421 /* If there are concurrent session enable SW frame translation
2422 * for all registered STA
2423 * This is not required in case of PRIMA as HW frame translation
2424 * is disabled in PRIMA*/
2425 if (vos_concurrent_sessions_running())
2426 {
2427 WLANTL_ConfigureSwFrameTXXlationForAll(pHddCtx->pvosContext, TRUE);
2428 }
2429#endif
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07002430 //Initialize the WoWL service
2431 if(!hdd_init_wowl(pAdapter))
2432 {
2433 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
2434 goto err_free_netdev;
2435 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002436 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002437 return pAdapter;
2438
2439err_free_netdev:
2440 free_netdev(pAdapter->dev);
2441 wlan_hdd_release_intf_addr( pHddCtx,
2442 pAdapter->macAddressCurrent.bytes );
2443
2444resume_bmps:
2445 //If bmps disabled enable it
2446 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
2447 {
2448 hdd_enable_bmps_imps(pHddCtx);
2449 }
2450 return NULL;
2451}
2452
2453VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
2454 tANI_U8 rtnl_held )
2455{
2456 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
2457 VOS_STATUS status;
2458
2459 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
2460 if( VOS_STATUS_SUCCESS != status )
2461 return status;
2462
2463 while ( pCurrent->pAdapter != pAdapter )
2464 {
2465 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
2466 if( VOS_STATUS_SUCCESS != status )
2467 break;
2468
2469 pCurrent = pNext;
2470 }
2471 pAdapterNode = pCurrent;
2472 if( VOS_STATUS_SUCCESS == status )
2473 {
2474 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2475 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
2476 hdd_remove_adapter( pHddCtx, pAdapterNode );
2477 vos_mem_free( pAdapterNode );
2478
2479#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
2480 /* If there is no concurrent session disable SW frame translation
2481 * for all registered STA */
2482 /* This is not required in case of PRIMA as HW frame translation
2483 * is disabled in PRIMA*/
2484 if (!vos_concurrent_sessions_running())
2485 {
2486 WLANTL_ConfigureSwFrameTXXlationForAll(pHddCtx->pvosContext, FALSE);
2487 }
2488#endif
2489
2490 /* If there is a single session of STA/P2P client, re-enable BMPS */
2491 if ((!vos_concurrent_sessions_running()) &&
2492 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
2493 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
2494 {
2495 hdd_enable_bmps_imps(pHddCtx);
2496 }
2497
2498 return VOS_STATUS_SUCCESS;
2499 }
2500
2501 return VOS_STATUS_E_FAILURE;
2502}
2503
2504VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
2505{
2506 hdd_adapter_list_node_t *pHddAdapterNode;
2507 VOS_STATUS status;
2508
2509 ENTER();
2510
2511 do
2512 {
2513 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
2514 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
2515 {
2516 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
2517 vos_mem_free( pHddAdapterNode );
2518 }
2519 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
2520
2521 EXIT();
2522
2523 return VOS_STATUS_SUCCESS;
2524}
2525
2526void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
2527{
2528 v_U8_t addIE[1] = {0};
2529
2530 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2531 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
2532 eANI_BOOLEAN_FALSE) )
2533 {
2534 hddLog(LOGE,
2535 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
2536 }
2537
2538 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2539 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
2540 eANI_BOOLEAN_FALSE) )
2541 {
2542 hddLog(LOGE,
2543 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
2544 }
2545
2546 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2547 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
2548 eANI_BOOLEAN_FALSE) )
2549 {
2550 hddLog(LOGE,
2551 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
2552 }
2553}
2554
2555VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2556{
2557 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2558 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2559 union iwreq_data wrqu;
2560
2561 ENTER();
2562
2563 switch(pAdapter->device_mode)
2564 {
2565 case WLAN_HDD_INFRA_STATION:
2566 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002567 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002568 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
2569 {
2570 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
2571 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
2572 pAdapter->sessionId,
2573 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
2574 else
2575 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
2576 pAdapter->sessionId,
2577 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2578 //success implies disconnect command got queued up successfully
2579 if(halStatus == eHAL_STATUS_SUCCESS)
2580 {
2581 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
2582 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2583 }
2584 memset(&wrqu, '\0', sizeof(wrqu));
2585 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2586 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2587 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2588 }
2589 else
2590 {
2591 hdd_abort_mac_scan(pHddCtx);
2592 }
2593
2594 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
2595 {
2596 INIT_COMPLETION(pAdapter->session_close_comp_var);
2597 if (eHAL_STATUS_SUCCESS ==
2598 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
2599 hdd_smeCloseSessionCallback, pAdapter))
2600 {
2601 //Block on a completion variable. Can't wait forever though.
2602 wait_for_completion_interruptible_timeout(
2603 &pAdapter->session_close_comp_var,
2604 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2605 }
2606 }
2607
2608 break;
2609
2610 case WLAN_HDD_SOFTAP:
2611 case WLAN_HDD_P2P_GO:
2612 //Any softap specific cleanup here...
2613 mutex_lock(&pHddCtx->sap_lock);
2614 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2615 {
2616 VOS_STATUS status;
2617 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2618
2619 //Stop Bss.
2620 status = WLANSAP_StopBss(pHddCtx->pvosContext);
2621 if (VOS_IS_STATUS_SUCCESS(status))
2622 {
2623 hdd_hostapd_state_t *pHostapdState =
2624 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2625
2626 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2627
2628 if (!VOS_IS_STATUS_SUCCESS(status))
2629 {
2630 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002631 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002632 }
2633 }
2634 else
2635 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002636 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002637 }
2638 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2639
2640 if (eHAL_STATUS_FAILURE ==
2641 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
2642 0, NULL, eANI_BOOLEAN_FALSE))
2643 {
2644 hddLog(LOGE,
2645 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002646 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002647 }
2648
2649 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2650 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2651 eANI_BOOLEAN_FALSE) )
2652 {
2653 hddLog(LOGE,
2654 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
2655 }
2656
2657 // Reset WNI_CFG_PROBE_RSP Flags
2658 wlan_hdd_reset_prob_rspies(pAdapter);
2659 kfree(pAdapter->sessionCtx.ap.beacon);
2660 pAdapter->sessionCtx.ap.beacon = NULL;
2661 }
2662 mutex_unlock(&pHddCtx->sap_lock);
2663 break;
2664 case WLAN_HDD_MONITOR:
2665 break;
2666 default:
2667 break;
2668 }
2669
2670 EXIT();
2671 return VOS_STATUS_SUCCESS;
2672}
2673
2674VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
2675{
2676 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2677 VOS_STATUS status;
2678 hdd_adapter_t *pAdapter;
2679
2680 ENTER();
2681
2682 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2683
2684 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2685 {
2686 pAdapter = pAdapterNode->pAdapter;
2687 netif_tx_disable(pAdapter->dev);
2688 netif_carrier_off(pAdapter->dev);
2689
2690 hdd_stop_adapter( pHddCtx, pAdapter );
2691
2692 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2693 pAdapterNode = pNext;
2694 }
2695
2696 EXIT();
2697
2698 return VOS_STATUS_SUCCESS;
2699}
2700
2701VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
2702{
2703 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2704 VOS_STATUS status;
2705 hdd_adapter_t *pAdapter;
2706
2707 ENTER();
2708
2709 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2710
2711 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2712 {
2713 pAdapter = pAdapterNode->pAdapter;
2714 netif_tx_disable(pAdapter->dev);
2715 netif_carrier_off(pAdapter->dev);
2716
2717 //Record whether STA is associated
2718 pAdapter->sessionCtx.station.bSendDisconnect =
2719 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
2720 VOS_TRUE : VOS_FALSE;
2721
2722 hdd_deinit_tx_rx(pAdapter);
2723 hdd_wmm_adapter_close(pAdapter);
2724
2725 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2726 pAdapterNode = pNext;
2727 }
2728
2729 EXIT();
2730
2731 return VOS_STATUS_SUCCESS;
2732}
2733
2734VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
2735{
2736 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2737 VOS_STATUS status;
2738 hdd_adapter_t *pAdapter;
2739 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
2740
2741 ENTER();
2742
2743 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2744
2745 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2746 {
2747 pAdapter = pAdapterNode->pAdapter;
2748
2749 switch(pAdapter->device_mode)
2750 {
2751 case WLAN_HDD_INFRA_STATION:
2752 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002753 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002754 hdd_init_station_mode(pAdapter);
2755 /* Open the gates for HDD to receive Wext commands */
2756 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002757 pHddCtx->scan_info.mScanPending = FALSE;
2758 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002759
2760 //Trigger the initial scan
2761 hdd_wlan_initial_scan(pAdapter);
2762
2763 //Indicate disconnect event to supplicant if associated previously
2764 if(pAdapter->sessionCtx.station.bSendDisconnect)
2765 {
2766 union iwreq_data wrqu;
2767 memset(&wrqu, '\0', sizeof(wrqu));
2768 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2769 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2770 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2771 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
2772
2773#ifdef CONFIG_CFG80211
2774 /* indicate disconnected event to nl80211 */
2775 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
2776 NULL, 0, GFP_KERNEL);
2777#endif
2778 }
2779 break;
2780
2781 case WLAN_HDD_SOFTAP:
2782 /* softAP can handle SSR */
2783 break;
2784
2785 case WLAN_HDD_P2P_GO:
2786#ifdef CONFIG_CFG80211
2787 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
2788 __func__);
2789 /* event supplicant to restart */
2790 cfg80211_del_sta(pAdapter->dev,
2791 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
2792#endif
2793 break;
2794
2795 case WLAN_HDD_MONITOR:
2796 /* monitor interface start */
2797 break;
2798 default:
2799 break;
2800 }
2801
2802 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2803 pAdapterNode = pNext;
2804 }
2805
2806 EXIT();
2807
2808 return VOS_STATUS_SUCCESS;
2809}
2810
2811VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
2812{
2813 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2814 hdd_adapter_t *pAdapter;
2815 VOS_STATUS status;
2816 v_U32_t roamId;
2817
2818 ENTER();
2819
2820 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2821
2822 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2823 {
2824 pAdapter = pAdapterNode->pAdapter;
2825
2826 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
2827 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
2828 {
2829 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2830 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2831
2832 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2833 init_completion(&pAdapter->disconnect_comp_var);
2834 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
2835 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2836
2837 wait_for_completion_interruptible_timeout(
2838 &pAdapter->disconnect_comp_var,
2839 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2840
2841 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
2842 pHddCtx->isAmpAllowed = VOS_FALSE;
2843 sme_RoamConnect(pHddCtx->hHal,
2844 pAdapter->sessionId, &(pWextState->roamProfile),
2845 &roamId);
2846 }
2847
2848 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2849 pAdapterNode = pNext;
2850 }
2851
2852 EXIT();
2853
2854 return VOS_STATUS_SUCCESS;
2855}
2856
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002857bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07002858{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002859 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07002860}
2861
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002862/* Once SSR is disabled then it cannot be set. */
2863void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07002864{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002865 if (HDD_SSR_DISABLED == isSsrRequired)
2866 return;
2867
Jeff Johnson295189b2012-06-20 16:38:30 -07002868 isSsrRequired = value;
2869}
2870
2871VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
2872 hdd_adapter_list_node_t** ppAdapterNode)
2873{
2874 VOS_STATUS status;
2875 spin_lock(&pHddCtx->hddAdapters.lock);
2876 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
2877 (hdd_list_node_t**) ppAdapterNode );
2878 spin_unlock(&pHddCtx->hddAdapters.lock);
2879 return status;
2880}
2881
2882VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
2883 hdd_adapter_list_node_t* pAdapterNode,
2884 hdd_adapter_list_node_t** pNextAdapterNode)
2885{
2886 VOS_STATUS status;
2887 spin_lock(&pHddCtx->hddAdapters.lock);
2888 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
2889 (hdd_list_node_t*) pAdapterNode,
2890 (hdd_list_node_t**)pNextAdapterNode );
2891
2892 spin_unlock(&pHddCtx->hddAdapters.lock);
2893 return status;
2894}
2895
2896VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
2897 hdd_adapter_list_node_t* pAdapterNode)
2898{
2899 VOS_STATUS status;
2900 spin_lock(&pHddCtx->hddAdapters.lock);
2901 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
2902 &pAdapterNode->node );
2903 spin_unlock(&pHddCtx->hddAdapters.lock);
2904 return status;
2905}
2906
2907VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
2908 hdd_adapter_list_node_t** ppAdapterNode)
2909{
2910 VOS_STATUS status;
2911 spin_lock(&pHddCtx->hddAdapters.lock);
2912 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
2913 (hdd_list_node_t**) ppAdapterNode );
2914 spin_unlock(&pHddCtx->hddAdapters.lock);
2915 return status;
2916}
2917
2918VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
2919 hdd_adapter_list_node_t* pAdapterNode)
2920{
2921 VOS_STATUS status;
2922 spin_lock(&pHddCtx->hddAdapters.lock);
2923 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
2924 (hdd_list_node_t*) pAdapterNode );
2925 spin_unlock(&pHddCtx->hddAdapters.lock);
2926 return status;
2927}
2928
2929VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
2930 hdd_adapter_list_node_t* pAdapterNode)
2931{
2932 VOS_STATUS status;
2933 spin_lock(&pHddCtx->hddAdapters.lock);
2934 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
2935 (hdd_list_node_t*) pAdapterNode );
2936 spin_unlock(&pHddCtx->hddAdapters.lock);
2937 return status;
2938}
2939
2940hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
2941 tSirMacAddr macAddr )
2942{
2943 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2944 hdd_adapter_t *pAdapter;
2945 VOS_STATUS status;
2946
2947 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2948
2949 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2950 {
2951 pAdapter = pAdapterNode->pAdapter;
2952
2953 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
2954 macAddr, sizeof(tSirMacAddr) ) )
2955 {
2956 return pAdapter;
2957 }
2958 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2959 pAdapterNode = pNext;
2960 }
2961
2962 return NULL;
2963
2964}
2965
2966hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
2967{
2968 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2969 hdd_adapter_t *pAdapter;
2970 VOS_STATUS status;
2971
2972 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2973
2974 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2975 {
2976 pAdapter = pAdapterNode->pAdapter;
2977
2978 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
2979 IFNAMSIZ ) )
2980 {
2981 return pAdapter;
2982 }
2983 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2984 pAdapterNode = pNext;
2985 }
2986
2987 return NULL;
2988
2989}
2990
2991hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
2992{
2993 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2994 hdd_adapter_t *pAdapter;
2995 VOS_STATUS status;
2996
2997 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2998
2999 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3000 {
3001 pAdapter = pAdapterNode->pAdapter;
3002
3003 if( pAdapter && (mode == pAdapter->device_mode) )
3004 {
3005 return pAdapter;
3006 }
3007 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3008 pAdapterNode = pNext;
3009 }
3010
3011 return NULL;
3012
3013}
3014
3015//Remove this function later
3016hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
3017{
3018 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3019 hdd_adapter_t *pAdapter;
3020 VOS_STATUS status;
3021
3022 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3023
3024 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3025 {
3026 pAdapter = pAdapterNode->pAdapter;
3027
3028 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
3029 {
3030 return pAdapter;
3031 }
3032
3033 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3034 pAdapterNode = pNext;
3035 }
3036
3037 return NULL;
3038
3039}
3040
3041#ifdef CONFIG_CFG80211
3042/**---------------------------------------------------------------------------
3043
3044 \brief hdd_set_monitor_tx_adapter() -
3045
3046 This API initializes the adapter to be used while transmitting on monitor
3047 adapter.
3048
3049 \param - pHddCtx - Pointer to the HDD context.
3050 pAdapter - Adapter that will used for TX. This can be NULL.
3051 \return - None.
3052 --------------------------------------------------------------------------*/
3053void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3054{
3055 hdd_adapter_t *pMonAdapter;
3056
3057 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
3058
3059 if( NULL != pMonAdapter )
3060 {
3061 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
3062 }
3063}
3064#endif
3065/**---------------------------------------------------------------------------
3066
3067 \brief hdd_select_queue() -
3068
3069 This API returns the operating channel of the requested device mode
3070
3071 \param - pHddCtx - Pointer to the HDD context.
3072 - mode - Device mode for which operating channel is required
3073 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
3074 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
3075 \return - channel number. "0" id the requested device is not found OR it is not connected.
3076 --------------------------------------------------------------------------*/
3077v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
3078{
3079 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3080 VOS_STATUS status;
3081 hdd_adapter_t *pAdapter;
3082 v_U8_t operatingChannel = 0;
3083
3084 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3085
3086 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3087 {
3088 pAdapter = pAdapterNode->pAdapter;
3089
3090 if( mode == pAdapter->device_mode )
3091 {
3092 switch(pAdapter->device_mode)
3093 {
3094 case WLAN_HDD_INFRA_STATION:
3095 case WLAN_HDD_P2P_CLIENT:
3096 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3097 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
3098 break;
3099 case WLAN_HDD_SOFTAP:
3100 case WLAN_HDD_P2P_GO:
3101 /*softap connection info */
3102 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3103 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
3104 break;
3105 default:
3106 break;
3107 }
3108
3109 break; //Found the device of interest. break the loop
3110 }
3111
3112 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3113 pAdapterNode = pNext;
3114 }
3115 return operatingChannel;
3116}
3117
3118#ifdef WLAN_FEATURE_PACKET_FILTERING
3119/**---------------------------------------------------------------------------
3120
3121 \brief hdd_set_multicast_list() -
3122
3123 This used to set the multicast address list.
3124
3125 \param - dev - Pointer to the WLAN device.
3126 - skb - Pointer to OS packet (sk_buff).
3127 \return - success/fail
3128
3129 --------------------------------------------------------------------------*/
3130static void hdd_set_multicast_list(struct net_device *dev)
3131{
3132 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07003133 int mc_count;
3134 int i = 0;
3135 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303136
3137 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07003138 {
3139 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303140 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003141 return;
3142 }
3143
3144 if (dev->flags & IFF_ALLMULTI)
3145 {
3146 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003147 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303148 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003149 }
3150 else
3151 {
3152 mc_count = netdev_mc_count(dev);
3153 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003154 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07003155 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
3156 {
3157 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003158 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303159 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003160 return;
3161 }
3162
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303163 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07003164
3165 netdev_for_each_mc_addr(ha, dev) {
3166 if (i == mc_count)
3167 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303168 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
3169 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
3170 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003171 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303172 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07003173 i++;
3174 }
3175 }
3176 return;
3177}
3178#endif
3179
3180/**---------------------------------------------------------------------------
3181
3182 \brief hdd_select_queue() -
3183
3184 This function is registered with the Linux OS for network
3185 core to decide which queue to use first.
3186
3187 \param - dev - Pointer to the WLAN device.
3188 - skb - Pointer to OS packet (sk_buff).
3189 \return - ac, Queue Index/access category corresponding to UP in IP header
3190
3191 --------------------------------------------------------------------------*/
3192v_U16_t hdd_select_queue(struct net_device *dev,
3193 struct sk_buff *skb)
3194{
3195 return hdd_wmm_select_queue(dev, skb);
3196}
3197
3198
3199/**---------------------------------------------------------------------------
3200
3201 \brief hdd_wlan_initial_scan() -
3202
3203 This function triggers the initial scan
3204
3205 \param - pAdapter - Pointer to the HDD adapter.
3206
3207 --------------------------------------------------------------------------*/
3208void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
3209{
3210 tCsrScanRequest scanReq;
3211 tCsrChannelInfo channelInfo;
3212 eHalStatus halStatus;
3213 unsigned long scanId;
3214 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3215
3216 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
3217 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
3218 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
3219
3220 if(sme_Is11dSupported(pHddCtx->hHal))
3221 {
3222 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
3223 if ( HAL_STATUS_SUCCESS( halStatus ) )
3224 {
3225 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
3226 if( !scanReq.ChannelInfo.ChannelList )
3227 {
3228 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
3229 vos_mem_free(channelInfo.ChannelList);
3230 return;
3231 }
3232 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
3233 channelInfo.numOfChannels);
3234 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
3235 vos_mem_free(channelInfo.ChannelList);
3236 }
3237
3238 scanReq.scanType = eSIR_PASSIVE_SCAN;
3239 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
3240 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
3241 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
3242 }
3243 else
3244 {
3245 scanReq.scanType = eSIR_ACTIVE_SCAN;
3246 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
3247 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
3248 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
3249 }
3250
3251 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
3252 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3253 {
3254 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
3255 __func__, halStatus );
3256 }
3257
3258 if(sme_Is11dSupported(pHddCtx->hHal))
3259 vos_mem_free(scanReq.ChannelInfo.ChannelList);
3260}
3261
3262struct fullPowerContext
3263{
3264 struct completion completion;
3265 unsigned int magic;
3266};
3267#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
3268
3269/**---------------------------------------------------------------------------
3270
3271 \brief hdd_full_power_callback() - HDD full power callback function
3272
3273 This is the function invoked by SME to inform the result of a full power
3274 request issued by HDD
3275
3276 \param - callbackcontext - Pointer to cookie
3277 \param - status - result of request
3278
3279 \return - None
3280
3281 --------------------------------------------------------------------------*/
3282static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
3283{
3284 struct fullPowerContext *pContext = callbackContext;
3285
3286 hddLog(VOS_TRACE_LEVEL_INFO,
3287 "%s: context = %p, status = %d", pContext, status);
3288
3289 if (NULL == callbackContext)
3290 {
3291 hddLog(VOS_TRACE_LEVEL_ERROR,
3292 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003293 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07003294 return;
3295 }
3296
3297 /* there is a race condition that exists between this callback function
3298 and the caller since the caller could time out either before or
3299 while this code is executing. we'll assume the timeout hasn't
3300 occurred, but we'll verify that right before we save our work */
3301
3302 if (POWER_CONTEXT_MAGIC != pContext->magic)
3303 {
3304 /* the caller presumably timed out so there is nothing we can do */
3305 hddLog(VOS_TRACE_LEVEL_WARN,
3306 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003307 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07003308 return;
3309 }
3310
3311 /* the race is on. caller could have timed out immediately after
3312 we verified the magic, but if so, caller will wait a short time
3313 for us to notify the caller, so the context will stay valid */
3314 complete(&pContext->completion);
3315}
3316
3317/**---------------------------------------------------------------------------
3318
3319 \brief hdd_wlan_exit() - HDD WLAN exit function
3320
3321 This is the driver exit point (invoked during rmmod)
3322
3323 \param - pHddCtx - Pointer to the HDD Context
3324
3325 \return - None
3326
3327 --------------------------------------------------------------------------*/
3328void hdd_wlan_exit(hdd_context_t *pHddCtx)
3329{
3330 eHalStatus halStatus;
3331 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
3332 VOS_STATUS vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07003333#ifdef CONFIG_CFG80211
3334 struct wiphy *wiphy = pHddCtx->wiphy;
3335#endif
3336#ifdef FEATURE_WLAN_INTEGRATED_SOC
3337 hdd_adapter_t* pAdapter;
3338#endif
3339 struct fullPowerContext powerContext;
3340 long lrc;
3341
3342 ENTER();
3343
Ng Chilam1322ea32012-12-27 17:33:08 -08003344#ifdef ANI_MANF_DIAG
3345 if (VOS_FTM_MODE != hdd_get_conparam())
3346#endif /* ANI_MANF_DIAG */
3347 {
3348 // Unloading, restart logic is no more required.
3349 wlan_hdd_restart_deinit(pHddCtx);
3350 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003351
Jeff Johnson295189b2012-06-20 16:38:30 -07003352#ifdef CONFIG_CFG80211
3353#ifdef WLAN_SOFTAP_FEATURE
3354 if (VOS_STA_SAP_MODE != hdd_get_conparam())
3355#endif
3356 {
3357#ifdef ANI_MANF_DIAG
3358 if (VOS_FTM_MODE != hdd_get_conparam())
3359#endif /* ANI_MANF_DIAG */
3360 {
3361 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
3362 WLAN_HDD_INFRA_STATION);
3363 if (pAdapter == NULL)
3364 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3365
3366 if (pAdapter != NULL)
3367 {
3368 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
3369 hdd_UnregisterWext(pAdapter->dev);
3370 }
3371 }
3372 }
3373#endif
3374
3375#ifdef ANI_MANF_DIAG
3376 if (VOS_FTM_MODE == hdd_get_conparam())
3377 {
3378 wlan_hdd_ftm_close(pHddCtx);
3379 goto free_hdd_ctx;
3380 }
3381#endif
3382 //Stop the Interface TX queue.
3383 //netif_tx_disable(pWlanDev);
3384 //netif_carrier_off(pWlanDev);
3385
Jeff Johnson295189b2012-06-20 16:38:30 -07003386#ifdef FEATURE_WLAN_INTEGRATED_SOC
3387#ifdef WLAN_SOFTAP_FEATURE
3388 if (VOS_STA_SAP_MODE == hdd_get_conparam())
3389 {
3390 pAdapter = hdd_get_adapter(pHddCtx,
3391 WLAN_HDD_SOFTAP);
3392 }
3393 else
3394 {
3395#endif
3396#ifdef ANI_MANF_DIAG
3397 if (VOS_FTM_MODE != hdd_get_conparam())
3398#endif /* ANI_MANF_DIAG */
3399 {
3400 pAdapter = hdd_get_adapter(pHddCtx,
3401 WLAN_HDD_INFRA_STATION);
3402 }
3403#ifdef WLAN_SOFTAP_FEATURE
3404 }
3405#endif
3406 /* DeRegister with platform driver as client for Suspend/Resume */
3407 vosStatus = hddDeregisterPmOps(pHddCtx);
3408 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3409 {
3410 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
3411 VOS_ASSERT(0);
3412 }
3413
3414 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
3415 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3416 {
3417 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
3418 }
3419#endif //FEATURE_WLAN_INTEGRATED_SOC
3420
Chilam NG571c65a2013-01-19 12:27:36 +05303421#ifdef FEATURE_WLAN_TDLS
3422 wlan_hdd_tdls_exit();
3423#endif
3424
Jeff Johnson295189b2012-06-20 16:38:30 -07003425 // Cancel any outstanding scan requests. We are about to close all
3426 // of our adapters, but an adapter structure is what SME passes back
3427 // to our callback function. Hence if there are any outstanding scan
3428 // requests then there is a race condition between when the adapter
3429 // is closed and when the callback is invoked. We try to resolve that
3430 // race condition here by canceling any outstanding scans before we
3431 // close the adapters.
3432 // Note that the scans may be cancelled in an asynchronous manner, so
3433 // ideally there needs to be some kind of synchronization. Rather than
3434 // introduce a new synchronization here, we will utilize the fact that
3435 // we are about to Request Full Power, and since that is synchronized,
3436 // the expectation is that by the time Request Full Power has completed,
3437 // all scans will be cancelled.
3438 hdd_abort_mac_scan( pHddCtx );
3439
3440 //Disable IMPS/BMPS as we do not want the device to enter any power
3441 //save mode during shutdown
3442 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3443 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3444 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
3445
3446 //Ensure that device is in full power as we will touch H/W during vos_Stop
3447 init_completion(&powerContext.completion);
3448 powerContext.magic = POWER_CONTEXT_MAGIC;
3449
3450 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
3451 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
3452
3453 if (eHAL_STATUS_SUCCESS != halStatus)
3454 {
3455 if (eHAL_STATUS_PMC_PENDING == halStatus)
3456 {
3457 /* request was sent -- wait for the response */
3458 lrc = wait_for_completion_interruptible_timeout(
3459 &powerContext.completion,
3460 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
3461 /* either we have a response or we timed out
3462 either way, first invalidate our magic */
3463 powerContext.magic = 0;
3464 if (lrc <= 0)
3465 {
3466 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003467 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07003468 /* there is a race condition such that the callback
3469 function could be executing at the same time we are. of
3470 primary concern is if the callback function had already
3471 verified the "magic" but hasn't yet set the completion
3472 variable. Since the completion variable is on our
3473 stack, we'll delay just a bit to make sure the data is
3474 still valid if that is the case */
3475 msleep(50);
3476 }
3477 }
3478 else
3479 {
3480 hddLog(VOS_TRACE_LEVEL_ERROR,
3481 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003482 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07003483 VOS_ASSERT(0);
3484 /* continue -- need to clean up as much as possible */
3485 }
3486 }
3487
3488 // Unregister the Net Device Notifier
3489 unregister_netdevice_notifier(&hdd_netdev_notifier);
3490
Jeff Johnson295189b2012-06-20 16:38:30 -07003491 hdd_stop_all_adapters( pHddCtx );
3492
Jeff Johnson295189b2012-06-20 16:38:30 -07003493#ifdef WLAN_BTAMP_FEATURE
3494 vosStatus = WLANBAP_Stop(pVosContext);
3495 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3496 {
3497 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3498 "%s: Failed to stop BAP",__func__);
3499 }
3500#endif //WLAN_BTAMP_FEATURE
3501
3502 //Stop all the modules
3503 vosStatus = vos_stop( pVosContext );
3504 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3505 {
3506 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3507 "%s: Failed to stop VOSS",__func__);
3508 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3509 }
3510
Jeff Johnson295189b2012-06-20 16:38:30 -07003511 //Assert Deep sleep signal now to put Libra HW in lowest power state
3512 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
3513 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3514
3515 //Vote off any PMIC voltage supplies
3516 vos_chipPowerDown(NULL, NULL, NULL);
3517
3518 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
3519
3520 //Clean up HDD Nlink Service
3521 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
3522 nl_srv_exit();
3523
3524 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07003525 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003526
3527 //Close the scheduler before calling vos_close to make sure no thread is
3528 // scheduled after the each module close is called i.e after all the data
3529 // structures are freed.
3530 vosStatus = vos_sched_close( pVosContext );
3531 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
3532 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
3533 "%s: Failed to close VOSS Scheduler",__func__);
3534 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3535 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003536#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07003537#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3538 /* Destroy the wake lock */
3539 wake_lock_destroy(&pHddCtx->rx_wake_lock);
3540#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08003541 /* Destroy the wake lock */
3542 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003543#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003544
3545 //Close VOSS
3546 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
3547 vos_close(pVosContext);
3548
Jeff Johnson295189b2012-06-20 16:38:30 -07003549 //Close Watchdog
3550 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3551 vos_watchdog_close(pVosContext);
3552
3553 /* Cancel the vote for XO Core ON.
3554 * This is done here to ensure there is no race condition since MC, TX and WD threads have
3555 * exited at this point
3556 */
3557 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
3558 " when WLAN is turned OFF\n");
3559 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
3560 {
3561 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
3562 " Not returning failure."
3563 " Power consumed will be high\n");
3564 }
3565
3566 hdd_close_all_adapters( pHddCtx );
3567
3568
3569 //Free up dynamically allocated members inside HDD Adapter
3570 kfree(pHddCtx->cfg_ini);
3571 pHddCtx->cfg_ini= NULL;
3572
3573 /* free the power on lock from platform driver */
3574 if (free_riva_power_on_lock("wlan"))
3575 {
3576 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
3577 __func__);
3578 }
3579
3580#ifdef ANI_MANF_DIAG
3581free_hdd_ctx:
3582#endif
3583#ifdef CONFIG_CFG80211
3584 wiphy_unregister(wiphy) ;
3585 wiphy_free(wiphy) ;
3586#else
3587 vos_mem_free( pHddCtx );
3588#endif
3589 if (hdd_is_ssr_required())
3590 {
3591 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07003592 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07003593 msleep(5000);
3594 }
3595 hdd_set_ssr_required (VOS_FALSE);
3596}
3597
3598
3599/**---------------------------------------------------------------------------
3600
3601 \brief hdd_update_config_from_nv() - Function to update the contents of
3602 the running configuration with parameters taken from NV storage
3603
3604 \param - pHddCtx - Pointer to the HDD global context
3605
3606 \return - VOS_STATUS_SUCCESS if successful
3607
3608 --------------------------------------------------------------------------*/
3609static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
3610{
3611#ifndef FEATURE_WLAN_INTEGRATED_SOC
3612 eHalStatus halStatus;
3613#endif
3614
3615#ifdef FEATURE_WLAN_INTEGRATED_SOC
3616 v_BOOL_t itemIsValid = VOS_FALSE;
3617 VOS_STATUS status;
3618 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
3619 v_U8_t macLoop;
3620
3621 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
3622 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
3623 if(status != VOS_STATUS_SUCCESS)
3624 {
3625 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
3626 return VOS_STATUS_E_FAILURE;
3627 }
3628
3629 if (itemIsValid == VOS_TRUE)
3630 {
3631 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
3632 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
3633 VOS_MAX_CONCURRENCY_PERSONA);
3634 if(status != VOS_STATUS_SUCCESS)
3635 {
3636 /* Get MAC from NV fail, not update CFG info
3637 * INI MAC value will be used for MAC setting */
3638 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
3639 return VOS_STATUS_E_FAILURE;
3640 }
3641
3642 /* If first MAC is not valid, treat all others are not valid
3643 * Then all MACs will be got from ini file */
3644 if(vos_is_macaddr_zero(&macFromNV[0]))
3645 {
3646 /* MAC address in NV file is not configured yet */
3647 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
3648 return VOS_STATUS_E_INVAL;
3649 }
3650
3651 /* Get MAC address from NV, update CFG info */
3652 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
3653 {
3654 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
3655 {
3656 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
3657 /* This MAC is not valid, skip it
3658 * This MAC will be got from ini file */
3659 }
3660 else
3661 {
3662 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
3663 (v_U8_t *)&macFromNV[macLoop].bytes[0],
3664 VOS_MAC_ADDR_SIZE);
3665 }
3666 }
3667 }
3668 else
3669 {
3670 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
3671 return VOS_STATUS_E_FAILURE;
3672 }
3673#endif /* FEATURE_WLAN_INTEGRATED_SOC */
3674
3675#ifndef FEATURE_WLAN_INTEGRATED_SOC
3676#if 1 /* need to fix for concurrency */
3677 // Set the MAC Address
3678 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
3679 halStatus = ccmCfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
3680 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
3681 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]),
3682 hdd_set_mac_addr_cb, VOS_FALSE );
3683
3684 if (!HAL_STATUS_SUCCESS( halStatus ))
3685 {
3686 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
3687 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
3688 return VOS_STATUS_E_FAILURE;
3689 }
3690#endif
3691#endif
3692
3693 return VOS_STATUS_SUCCESS;
3694}
3695
3696/**---------------------------------------------------------------------------
3697
3698 \brief hdd_post_voss_start_config() - HDD post voss start config helper
3699
3700 \param - pAdapter - Pointer to the HDD
3701
3702 \return - None
3703
3704 --------------------------------------------------------------------------*/
3705VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
3706{
3707 eHalStatus halStatus;
3708 v_U32_t listenInterval;
3709
3710#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
3711 /* In the non-integrated architecture we update the configuration from
3712 the INI file and from NV after vOSS has been started
3713 */
3714
3715 // Apply the cfg.ini to cfg.dat
3716 if (FALSE == hdd_update_config_dat(pHddCtx))
3717 {
3718 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
3719 return VOS_STATUS_E_FAILURE;
3720 }
3721
3722 // Apply the NV to cfg.dat
3723 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
3724 {
3725 hddLog(VOS_TRACE_LEVEL_FATAL,
3726 "%s: config update from NV failed", __func__ );
3727 return VOS_STATUS_E_FAILURE;
3728 }
3729#endif // FEATURE_WLAN_NON_INTEGRATED_SOC
3730
3731 // Send ready indication to the HDD. This will kick off the MAC
3732 // into a 'running' state and should kick off an initial scan.
3733 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
3734 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3735 {
3736 hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
3737 "code %08d [x%08x]",__func__, halStatus, halStatus );
3738 return VOS_STATUS_E_FAILURE;
3739 }
3740
3741 // Set default LI into HDD context,
3742 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
3743 // And RIVA will crash
3744 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
3745 pHddCtx->hdd_actual_LI_value = listenInterval;
3746
3747 return VOS_STATUS_SUCCESS;
3748}
3749
Jeff Johnson295189b2012-06-20 16:38:30 -07003750/* wake lock APIs for HDD */
3751void hdd_prevent_suspend(void)
3752{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003753#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003754 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003755#else
3756 wcnss_prevent_suspend();
3757#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003758}
3759
3760void hdd_allow_suspend(void)
3761{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003762#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003763 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003764#else
3765 wcnss_allow_suspend();
3766#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003767}
3768
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003769void hdd_allow_suspend_timeout(v_U32_t timeout)
3770{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003771#ifdef WLAN_OPEN_SOURCE
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003772 wake_lock_timeout(&wlan_wake_lock, timeout);
3773#else
3774 /* Do nothing as there is no API in wcnss for timeout*/
3775#endif
3776}
3777
Jeff Johnson295189b2012-06-20 16:38:30 -07003778/**---------------------------------------------------------------------------
3779
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003780 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
3781 information between Host and Riva
3782
3783 This function gets reported version of FW
3784 It also finds the version of Riva headers used to compile the host
3785 It compares the above two and prints a warning if they are different
3786 It gets the SW and HW version string
3787 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
3788 indicating the features they support through a bitmap
3789
3790 \param - pHddCtx - Pointer to HDD context
3791
3792 \return - void
3793
3794 --------------------------------------------------------------------------*/
3795
3796void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
3797{
3798
3799 tSirVersionType versionCompiled;
3800 tSirVersionType versionReported;
3801 tSirVersionString versionString;
3802 tANI_U8 fwFeatCapsMsgSupported = 0;
3803 VOS_STATUS vstatus;
3804
3805 /* retrieve and display WCNSS version information */
3806 do {
3807
3808 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
3809 &versionCompiled);
3810 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3811 {
3812 hddLog(VOS_TRACE_LEVEL_FATAL,
3813 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003814 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003815 break;
3816 }
3817
3818 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
3819 &versionReported);
3820 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3821 {
3822 hddLog(VOS_TRACE_LEVEL_FATAL,
3823 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003824 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003825 break;
3826 }
3827
3828 if ((versionCompiled.major != versionReported.major) ||
3829 (versionCompiled.minor != versionReported.minor) ||
3830 (versionCompiled.version != versionReported.version) ||
3831 (versionCompiled.revision != versionReported.revision))
3832 {
3833 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
3834 "Host expected %u.%u.%u.%u\n",
3835 WLAN_MODULE_NAME,
3836 (int)versionReported.major,
3837 (int)versionReported.minor,
3838 (int)versionReported.version,
3839 (int)versionReported.revision,
3840 (int)versionCompiled.major,
3841 (int)versionCompiled.minor,
3842 (int)versionCompiled.version,
3843 (int)versionCompiled.revision);
3844 }
3845 else
3846 {
3847 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
3848 WLAN_MODULE_NAME,
3849 (int)versionReported.major,
3850 (int)versionReported.minor,
3851 (int)versionReported.version,
3852 (int)versionReported.revision);
3853 }
3854
3855 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
3856 versionString,
3857 sizeof(versionString));
3858 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3859 {
3860 hddLog(VOS_TRACE_LEVEL_FATAL,
3861 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003862 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003863 break;
3864 }
3865
3866 pr_info("%s: WCNSS software version %s\n",
3867 WLAN_MODULE_NAME, versionString);
3868
3869 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
3870 versionString,
3871 sizeof(versionString));
3872 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3873 {
3874 hddLog(VOS_TRACE_LEVEL_FATAL,
3875 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003876 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003877 break;
3878 }
3879
3880 pr_info("%s: WCNSS hardware version %s\n",
3881 WLAN_MODULE_NAME, versionString);
3882
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003883 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
3884 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003885 send the message only if it the riva is 1.1
3886 minor numbers for different riva branches:
3887 0 -> (1.0)Mainline Build
3888 1 -> (1.1)Mainline Build
3889 2->(1.04) Stability Build
3890 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003891 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003892 ((versionReported.minor>=1) && (versionReported.version>=1)))
3893 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
3894 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003895
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003896 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08003897 {
3898#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
3899 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
3900 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
3901#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003902 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08003903 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003904
3905 } while (0);
3906
3907}
3908
3909/**---------------------------------------------------------------------------
3910
Jeff Johnson295189b2012-06-20 16:38:30 -07003911 \brief hdd_wlan_startup() - HDD init function
3912
3913 This is the driver startup code executed once a WLAN device has been detected
3914
3915 \param - dev - Pointer to the underlying device
3916
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003917 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07003918
3919 --------------------------------------------------------------------------*/
3920
3921int hdd_wlan_startup(struct device *dev )
3922{
3923 VOS_STATUS status;
3924 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003925 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003926 hdd_context_t *pHddCtx = NULL;
3927 v_CONTEXT_t pVosContext= NULL;
3928#ifdef WLAN_BTAMP_FEATURE
3929 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
3930 WLANBAP_ConfigType btAmpConfig;
3931 hdd_config_t *pConfig;
3932#endif
3933 int ret;
3934#ifdef CONFIG_CFG80211
3935 struct wiphy *wiphy;
3936#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003937
3938 ENTER();
3939#ifdef CONFIG_CFG80211
3940 /*
3941 * cfg80211: wiphy allocation
3942 */
3943 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
3944
3945 if(wiphy == NULL)
3946 {
3947 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003948 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003949 }
3950
3951 pHddCtx = wiphy_priv(wiphy);
3952
3953#else
3954
3955 pHddCtx = vos_mem_malloc ( sizeof( hdd_context_t ) );
3956 if(pHddCtx == NULL)
3957 {
3958 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003959 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07003960 }
3961
3962#endif
3963 //Initialize the adapter context to zeros.
3964 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
3965
3966#ifdef CONFIG_CFG80211
3967 pHddCtx->wiphy = wiphy;
3968#endif
3969 hdd_prevent_suspend();
3970 pHddCtx->isLoadUnloadInProgress = TRUE;
3971
3972 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
3973
3974 /*Get vos context here bcoz vos_open requires it*/
3975 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
3976
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08003977 if(pVosContext == NULL)
3978 {
3979 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
3980 goto err_free_hdd_context;
3981 }
3982
Jeff Johnson295189b2012-06-20 16:38:30 -07003983 //Save the Global VOSS context in adapter context for future.
3984 pHddCtx->pvosContext = pVosContext;
3985
3986 //Save the adapter context in global context for future.
3987 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
3988
Jeff Johnson295189b2012-06-20 16:38:30 -07003989 pHddCtx->parent_dev = dev;
3990
3991 init_completion(&pHddCtx->full_pwr_comp_var);
3992 init_completion(&pHddCtx->standby_comp_var);
3993 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003994 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003995 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003996
3997 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
3998
3999 // Load all config first as TL config is needed during vos_open
4000 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
4001 if(pHddCtx->cfg_ini == NULL)
4002 {
4003 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
4004 goto err_free_hdd_context;
4005 }
4006
4007 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
4008
4009 // Read and parse the qcom_cfg.ini file
4010 status = hdd_parse_config_ini( pHddCtx );
4011 if ( VOS_STATUS_SUCCESS != status )
4012 {
4013 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
4014 __func__, WLAN_INI_FILE);
4015 goto err_config;
4016 }
4017
4018#ifdef CONFIG_CFG80211
4019 /*
4020 * cfg80211: Initialization and registration ...
4021 */
4022 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
4023 {
4024 hddLog(VOS_TRACE_LEVEL_FATAL,
4025 "%s: wlan_hdd_cfg80211_register return failure", __func__);
4026 goto err_wiphy_reg;
4027 }
4028#endif
4029
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004030 // Update VOS trace levels based upon the cfg.ini
4031 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
4032 pHddCtx->cfg_ini->vosTraceEnableBAP);
4033 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
4034 pHddCtx->cfg_ini->vosTraceEnableTL);
4035 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
4036 pHddCtx->cfg_ini->vosTraceEnableWDI);
4037 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
4038 pHddCtx->cfg_ini->vosTraceEnableHDD);
4039 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
4040 pHddCtx->cfg_ini->vosTraceEnableSME);
4041 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
4042 pHddCtx->cfg_ini->vosTraceEnablePE);
4043 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
4044 pHddCtx->cfg_ini->vosTraceEnableWDA);
4045 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
4046 pHddCtx->cfg_ini->vosTraceEnableSYS);
4047 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
4048 pHddCtx->cfg_ini->vosTraceEnableVOSS);
4049#ifdef WLAN_SOFTAP_FEATURE
4050 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
4051 pHddCtx->cfg_ini->vosTraceEnableSAP);
4052 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
4053 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
4054#endif
4055
Jeff Johnson295189b2012-06-20 16:38:30 -07004056#ifdef FEATURE_WLAN_INTEGRATED_SOC
4057 // Update WDI trace levels based upon the cfg.ini
4058 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
4059 pHddCtx->cfg_ini->wdiTraceEnableDAL);
4060 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
4061 pHddCtx->cfg_ini->wdiTraceEnableCTL);
4062 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
4063 pHddCtx->cfg_ini->wdiTraceEnableDAT);
4064 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
4065 pHddCtx->cfg_ini->wdiTraceEnablePAL);
4066#endif /* FEATURE_WLAN_INTEGRATED_SOC */
4067
4068#ifdef ANI_MANF_DIAG
4069 if(VOS_FTM_MODE == hdd_get_conparam())
4070 {
4071 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
4072 {
4073 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
4074 goto err_free_hdd_context;
4075 }
4076 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
4077 return VOS_STATUS_SUCCESS;
4078 }
4079#endif
4080
4081 //Open watchdog module
4082 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4083 {
4084 status = vos_watchdog_open(pVosContext,
4085 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
4086
4087 if(!VOS_IS_STATUS_SUCCESS( status ))
4088 {
4089 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
4090#ifdef CONFIG_CFG80211
4091 goto err_wiphy_reg;
4092#else
4093 goto err_config;
4094#endif
4095 }
4096 }
4097
4098 pHddCtx->isLogpInProgress = FALSE;
4099 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4100
Jeff Johnson295189b2012-06-20 16:38:30 -07004101 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
4102 if(!VOS_IS_STATUS_SUCCESS(status))
4103 {
4104 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004105 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004106 }
4107
Jeff Johnson295189b2012-06-20 16:38:30 -07004108 status = vos_open( &pVosContext, 0);
4109 if ( !VOS_IS_STATUS_SUCCESS( status ))
4110 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004111 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
4112 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07004113 }
4114
Jeff Johnson295189b2012-06-20 16:38:30 -07004115 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
4116
4117 if ( NULL == pHddCtx->hHal )
4118 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004119 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004120 goto err_vosclose;
4121 }
4122
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004123 status = vos_preStart( pHddCtx->pvosContext );
4124 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4125 {
4126 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
4127 goto err_vosclose;
4128 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004129
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004130 /* Note that the vos_preStart() sequence triggers the cfg download.
4131 The cfg download must occur before we update the SME config
4132 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07004133 status = hdd_set_sme_config( pHddCtx );
4134
4135 if ( VOS_STATUS_SUCCESS != status )
4136 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004137 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
4138 goto err_vosclose;
4139 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004140
4141 //Initialize the WMM module
4142 status = hdd_wmm_init(pHddCtx);
4143 if (!VOS_IS_STATUS_SUCCESS(status))
4144 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004145 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004146 goto err_vosclose;
4147 }
4148
4149#ifdef FEATURE_WLAN_INTEGRATED_SOC
Jeff Johnson295189b2012-06-20 16:38:30 -07004150 /* In the integrated architecture we update the configuration from
4151 the INI file and from NV before vOSS has been started so that
4152 the final contents are available to send down to the cCPU */
4153
4154 // Apply the cfg.ini to cfg.dat
4155 if (FALSE == hdd_update_config_dat(pHddCtx))
4156 {
4157 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
4158 goto err_vosclose;
4159 }
4160
4161 // Apply the NV to cfg.dat
4162 /* Prima Update MAC address only at here */
4163 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
4164 {
4165#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
4166 /* There was not a valid set of MAC Addresses in NV. See if the
4167 default addresses were modified by the cfg.ini settings. If so,
4168 we'll use them, but if not, we'll autogenerate a set of MAC
4169 addresses based upon the device serial number */
4170
4171 static const v_MACADDR_t default_address =
4172 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
4173 unsigned int serialno;
4174 int i;
4175
4176 serialno = wcnss_get_serial_number();
4177 if ((0 != serialno) &&
4178 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
4179 sizeof(default_address))))
4180 {
4181 /* cfg.ini has the default address, invoke autogen logic */
4182
4183 /* MAC address has 3 bytes of OUI so we have a maximum of 3
4184 bytes of the serial number that can be used to generate
4185 the other 3 bytes of the MAC address. Mask off all but
4186 the lower 3 bytes (this will also make sure we don't
4187 overflow in the next step) */
4188 serialno &= 0x00FFFFFF;
4189
4190 /* we need a unique address for each session */
4191 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
4192
4193 /* autogen all addresses */
4194 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4195 {
4196 /* start with the entire default address */
4197 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
4198 /* then replace the lower 3 bytes */
4199 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
4200 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
4201 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
4202
4203 serialno++;
4204 }
4205
4206 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
4207 MAC_ADDRESS_STR,
4208 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4209 }
4210 else
4211#endif //WLAN_AUTOGEN_MACADDR_FEATURE
4212 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004213 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004214 "%s: Invalid MAC address in NV, using MAC from ini file "
4215 MAC_ADDRESS_STR, __func__,
4216 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4217 }
4218 }
4219 {
4220 eHalStatus halStatus;
4221 // Set the MAC Address
4222 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
4223 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
4224 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
4225 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
4226
4227 if (!HAL_STATUS_SUCCESS( halStatus ))
4228 {
4229 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
4230 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08004231 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004232 }
4233 }
4234#endif // FEATURE_WLAN_INTEGRATED_SOC
4235
4236 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
4237 Note: Firmware image will be read and downloaded inside vos_start API */
4238 status = vos_start( pHddCtx->pvosContext );
4239 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4240 {
4241 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
4242 goto err_vosclose;
4243 }
4244
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004245 /* Exchange capability info between Host and FW and also get versioning info from FW */
4246 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004247
4248 status = hdd_post_voss_start_config( pHddCtx );
4249 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4250 {
4251 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
4252 __func__);
4253 goto err_vosstop;
4254 }
4255
4256#ifdef WLAN_SOFTAP_FEATURE
4257 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4258 {
4259 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
4260 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4261 }
4262 else
4263 {
4264#endif
4265 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
4266 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4267 if (pAdapter != NULL)
4268 {
4269#ifdef WLAN_FEATURE_P2P
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304270 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07004271 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304272 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
4273 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
4274 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07004275
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304276 /* Generate the P2P Device Address. This consists of the device's
4277 * primary MAC address with the locally administered bit set.
4278 */
4279 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07004280 }
4281 else
4282 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304283 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
4284 if (p2p_dev_addr != NULL)
4285 {
4286 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
4287 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
4288 }
4289 else
4290 {
4291 hddLog(VOS_TRACE_LEVEL_FATAL,
4292 "%s: Failed to allocate mac_address for p2p_device",
4293 __func__);
4294 goto err_close_adapter;
4295 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004296 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004297
4298 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
4299 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
4300 if ( NULL == pP2pAdapter )
4301 {
4302 hddLog(VOS_TRACE_LEVEL_FATAL,
4303 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004304 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004305 goto err_close_adapter;
4306 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004307#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004308 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004309#ifdef WLAN_SOFTAP_FEATURE
4310 }
4311#endif
4312
4313 if( pAdapter == NULL )
4314 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004315 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
4316 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004317 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004318
Jeff Johnson295189b2012-06-20 16:38:30 -07004319#ifdef WLAN_BTAMP_FEATURE
4320 vStatus = WLANBAP_Open(pVosContext);
4321 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4322 {
4323 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4324 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004325 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004326 }
4327
4328 vStatus = BSL_Init(pVosContext);
4329 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4330 {
4331 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4332 "%s: Failed to Init BSL",__func__);
4333 goto err_bap_close;
4334 }
4335 vStatus = WLANBAP_Start(pVosContext);
4336 if (!VOS_IS_STATUS_SUCCESS(vStatus))
4337 {
4338 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4339 "%s: Failed to start TL",__func__);
4340 goto err_bap_close;
4341 }
4342
4343 pConfig = pHddCtx->cfg_ini;
4344 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
4345 status = WLANBAP_SetConfig(&btAmpConfig);
4346
4347#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07004348
Jeff Johnson295189b2012-06-20 16:38:30 -07004349#ifdef FEATURE_WLAN_SCAN_PNO
4350 /*SME must send channel update configuration to RIVA*/
4351 sme_UpdateChannelConfig(pHddCtx->hHal);
4352#endif
4353
4354#ifdef FEATURE_WLAN_INTEGRATED_SOC
4355 /* Register with platform driver as client for Suspend/Resume */
4356 status = hddRegisterPmOps(pHddCtx);
4357 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4358 {
4359 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
4360#ifdef WLAN_BTAMP_FEATURE
4361 goto err_bap_stop;
4362#else
Jeff Johnsone7245742012-09-05 17:12:55 -07004363 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004364#endif //WLAN_BTAMP_FEATURE
4365 }
4366
4367 /* Register TM level change handler function to the platform */
4368 status = hddDevTmRegisterNotifyCallback(pHddCtx);
4369 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4370 {
4371 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
4372 goto err_unregister_pmops;
4373 }
4374#endif
4375
4376 /* register for riva power on lock to platform driver */
4377 if (req_riva_power_on_lock("wlan"))
4378 {
4379 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
4380 __func__);
4381 goto err_unregister_pmops;
4382 }
4383
Jeff Johnson295189b2012-06-20 16:38:30 -07004384 // register net device notifier for device change notification
4385 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4386
4387 if(ret < 0)
4388 {
4389 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
4390 goto err_free_power_on_lock;
4391 }
4392
4393 //Initialize the nlink service
4394 if(nl_srv_init() != 0)
4395 {
4396 hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
4397 goto err_reg_netdev;
4398 }
4399
4400 //Initialize the BTC service
4401 if(btc_activate_service(pHddCtx) != 0)
4402 {
4403 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
4404 goto err_nl_srv;
4405 }
4406
4407#ifdef PTT_SOCK_SVC_ENABLE
4408 //Initialize the PTT service
4409 if(ptt_sock_activate_svc(pHddCtx) != 0)
4410 {
4411 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
4412 goto err_nl_srv;
4413 }
4414#endif
4415
Jeff Johnson295189b2012-06-20 16:38:30 -07004416 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004417#ifdef CONFIG_CFG80211
4418#ifdef WLAN_SOFTAP_FEATURE
4419 if (VOS_STA_SAP_MODE != hdd_get_conparam())
4420#endif
4421 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07004422 /* Action frame registered in one adapter which will
4423 * applicable to all interfaces
4424 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07004425 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07004426 }
4427#endif
4428
4429 mutex_init(&pHddCtx->sap_lock);
4430
4431 pHddCtx->isLoadUnloadInProgress = FALSE;
4432
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004433#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004434#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4435 /* Initialize the wake lcok */
4436 wake_lock_init(&pHddCtx->rx_wake_lock,
4437 WAKE_LOCK_SUSPEND,
4438 "qcom_rx_wakelock");
4439#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004440 /* Initialize the wake lcok */
4441 wake_lock_init(&pHddCtx->sap_wake_lock,
4442 WAKE_LOCK_SUSPEND,
4443 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004444#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004445
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004446 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
4447 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07004448
4449 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4450 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004451
4452 // Initialize the restart logic
4453 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05304454
4455#ifdef FEATURE_WLAN_TDLS
Hoonki Lee387663d2013-02-05 18:08:43 -08004456 if(0 != wlan_hdd_tdls_init(pAdapter->dev))
4457 {
4458 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_tdls_init failed",__func__);
4459 goto err_nl_srv;
4460 }
Chilam NG571c65a2013-01-19 12:27:36 +05304461#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004462
4463 goto success;
4464
4465err_nl_srv:
4466 nl_srv_exit();
4467
4468err_reg_netdev:
4469 unregister_netdevice_notifier(&hdd_netdev_notifier);
4470
4471err_free_power_on_lock:
4472 free_riva_power_on_lock("wlan");
4473
4474err_unregister_pmops:
4475 hddDevTmUnregisterNotifyCallback(pHddCtx);
4476 hddDeregisterPmOps(pHddCtx);
4477
4478#ifdef WLAN_BTAMP_FEATURE
4479err_bap_stop:
4480 WLANBAP_Stop(pVosContext);
4481#endif
4482
4483#ifdef WLAN_BTAMP_FEATURE
4484err_bap_close:
4485 WLANBAP_Close(pVosContext);
4486#endif
4487
Jeff Johnson295189b2012-06-20 16:38:30 -07004488err_close_adapter:
4489 hdd_close_all_adapters( pHddCtx );
4490
4491err_vosstop:
4492 vos_stop(pVosContext);
4493
4494err_vosclose:
4495 status = vos_sched_close( pVosContext );
4496 if (!VOS_IS_STATUS_SUCCESS(status)) {
4497 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4498 "%s: Failed to close VOSS Scheduler", __func__);
4499 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
4500 }
4501 vos_close(pVosContext );
4502
Jeff Johnson295189b2012-06-20 16:38:30 -07004503err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004504 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004505
4506err_wdclose:
4507 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4508 vos_watchdog_close(pVosContext);
4509
4510#ifdef CONFIG_CFG80211
4511err_wiphy_reg:
4512 wiphy_unregister(wiphy) ;
4513#endif
4514
4515err_config:
4516 kfree(pHddCtx->cfg_ini);
4517 pHddCtx->cfg_ini= NULL;
4518
4519err_free_hdd_context:
4520 hdd_allow_suspend();
4521#ifdef CONFIG_CFG80211
4522 wiphy_free(wiphy) ;
4523 //kfree(wdev) ;
4524#else
4525 vos_mem_free( pHddCtx );
4526#endif
4527 VOS_BUG(1);
4528
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08004529 if (hdd_is_ssr_required())
4530 {
4531 /* WDI timeout had happened during load, so SSR is needed here */
4532 subsystem_restart("wcnss");
4533 msleep(5000);
4534 }
4535 hdd_set_ssr_required (VOS_FALSE);
4536
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004537 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004538
4539success:
4540 EXIT();
4541 return 0;
4542}
4543
4544/**---------------------------------------------------------------------------
4545
Jeff Johnson32d95a32012-09-10 13:15:23 -07004546 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07004547
Jeff Johnson32d95a32012-09-10 13:15:23 -07004548 This is the driver entry point - called in different timeline depending
4549 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07004550
4551 \param - None
4552
4553 \return - 0 for success, non zero for failure
4554
4555 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07004556static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004557{
4558 VOS_STATUS status;
4559 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004560 struct device *dev = NULL;
4561 int ret_status = 0;
4562
4563 ENTER();
4564
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004565#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004566 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07004567#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004568
4569 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
4570 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
4571
4572 //Power Up Libra WLAN card first if not already powered up
4573 status = vos_chipPowerUp(NULL,NULL,NULL);
4574 if (!VOS_IS_STATUS_SUCCESS(status))
4575 {
4576 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
4577 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004578 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004579 }
4580
Jeff Johnson295189b2012-06-20 16:38:30 -07004581#ifdef ANI_BUS_TYPE_PCI
4582
4583 dev = wcnss_wlan_get_device();
4584
4585#endif // ANI_BUS_TYPE_PCI
4586
4587#ifdef ANI_BUS_TYPE_PLATFORM
4588 dev = wcnss_wlan_get_device();
4589#endif // ANI_BUS_TYPE_PLATFORM
4590
4591
4592 do {
4593 if (NULL == dev) {
4594 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
4595 ret_status = -1;
4596 break;
4597 }
4598
4599#ifdef MEMORY_DEBUG
4600 vos_mem_init();
4601#endif
4602
4603#ifdef TIMER_MANAGER
4604 vos_timer_manager_init();
4605#endif
4606
4607 /* Preopen VOSS so that it is ready to start at least SAL */
4608 status = vos_preOpen(&pVosContext);
4609
4610 if (!VOS_IS_STATUS_SUCCESS(status))
4611 {
4612 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
4613 ret_status = -1;
4614 break;
4615 }
4616
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004617#ifndef MODULE
4618 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
4619 */
4620 hdd_set_conparam((v_UINT_t)con_mode);
4621#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004622
4623 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004624 if (hdd_wlan_startup(dev))
4625 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004626 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004627 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004628 vos_preClose( &pVosContext );
4629 ret_status = -1;
4630 break;
4631 }
4632
4633 /* Cancel the vote for XO Core ON
4634 * This is done here for safety purposes in case we re-initialize without turning
4635 * it OFF in any error scenario.
4636 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004637 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07004638 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004639 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07004640 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4641 {
4642 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
4643 " Power consumed will be high\n");
4644 }
4645 } while (0);
4646
4647 if (0 != ret_status)
4648 {
4649 //Assert Deep sleep signal now to put Libra HW in lowest power state
4650 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4651 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
4652
4653 //Vote off any PMIC voltage supplies
4654 vos_chipPowerDown(NULL, NULL, NULL);
4655#ifdef TIMER_MANAGER
4656 vos_timer_exit();
4657#endif
4658#ifdef MEMORY_DEBUG
4659 vos_mem_exit();
4660#endif
4661
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004662#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004663 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004664#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004665 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
4666 }
4667 else
4668 {
4669 //Send WLAN UP indication to Nlink Service
4670 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
4671
4672 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
4673
4674 }
4675
4676 EXIT();
4677
4678 return ret_status;
4679}
4680
Jeff Johnson32d95a32012-09-10 13:15:23 -07004681/**---------------------------------------------------------------------------
4682
4683 \brief hdd_module_init() - Init Function
4684
4685 This is the driver entry point (invoked when module is loaded using insmod)
4686
4687 \param - None
4688
4689 \return - 0 for success, non zero for failure
4690
4691 --------------------------------------------------------------------------*/
4692#ifdef MODULE
4693static int __init hdd_module_init ( void)
4694{
4695 return hdd_driver_init();
4696}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004697#else /* #ifdef MODULE */
4698static int __init hdd_module_init ( void)
4699{
4700 /* Driver initialization is delayed to fwpath_changed_handler */
4701 return 0;
4702}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004703#endif /* #ifdef MODULE */
4704
Jeff Johnson295189b2012-06-20 16:38:30 -07004705
4706/**---------------------------------------------------------------------------
4707
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004708 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07004709
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004710 This is the driver exit point (invoked when module is unloaded using rmmod
4711 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07004712
4713 \param - None
4714
4715 \return - None
4716
4717 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004718static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004719{
4720 hdd_context_t *pHddCtx = NULL;
4721 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004722
4723 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
4724
4725 //Get the global vos context
4726 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4727
4728 if(!pVosContext)
4729 {
4730 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
4731 goto done;
4732 }
4733
4734 //Get the HDD context.
4735 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
4736
4737 if(!pHddCtx)
4738 {
4739 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
4740 }
4741 else
4742 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004743 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07004744 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07004745 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
4746 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07004747 }
4748
4749 pHddCtx->isLoadUnloadInProgress = TRUE;
4750 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4751
4752 //Do all the cleanup before deregistering the driver
4753 hdd_wlan_exit(pHddCtx);
4754 }
4755
Jeff Johnson295189b2012-06-20 16:38:30 -07004756 vos_preClose( &pVosContext );
4757
4758#ifdef TIMER_MANAGER
4759 vos_timer_exit();
4760#endif
4761#ifdef MEMORY_DEBUG
4762 vos_mem_exit();
4763#endif
4764
4765done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004766#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004767 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004768#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004769 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
4770}
4771
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004772/**---------------------------------------------------------------------------
4773
4774 \brief hdd_module_exit() - Exit function
4775
4776 This is the driver exit point (invoked when module is unloaded using rmmod)
4777
4778 \param - None
4779
4780 \return - None
4781
4782 --------------------------------------------------------------------------*/
4783static void __exit hdd_module_exit(void)
4784{
4785 hdd_driver_exit();
4786}
4787
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004788#ifdef MODULE
4789static int fwpath_changed_handler(const char *kmessage,
4790 struct kernel_param *kp)
4791{
4792 /* nothing to do when driver is DLKM */
4793 return 0;
4794}
4795
4796static int con_mode_handler(const char *kmessage,
4797 struct kernel_param *kp)
4798{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07004799 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004800}
4801#else /* #ifdef MODULE */
4802/**---------------------------------------------------------------------------
4803
4804 \brief fwpath_changed_handler() - Handler Function
4805
4806 This is the driver entry point
4807 - delayed driver initialization when driver is statically linked
4808 - invoked when module parameter fwpath is modified from userpspace to signal
4809 initializing the WLAN driver
4810
4811 \return - 0 for success, non zero for failure
4812
4813 --------------------------------------------------------------------------*/
4814static int fwpath_changed_handler(const char *kmessage,
4815 struct kernel_param *kp)
4816{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004817 int ret_status;
4818
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004819 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004820 ret_status = hdd_driver_init();
4821 wlan_hdd_inited = ret_status ? 0 : 1;
4822 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004823 }
4824
4825 hdd_driver_exit();
4826
4827 msleep(200);
4828
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004829 ret_status = hdd_driver_init();
4830 wlan_hdd_inited = ret_status ? 0 : 1;
4831 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004832}
4833
Jeff Johnson295189b2012-06-20 16:38:30 -07004834/**---------------------------------------------------------------------------
4835
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004836 \brief con_mode_handler() -
4837
4838 Handler function for module param con_mode when it is changed by userspace
4839 Dynamically linked - do nothing
4840 Statically linked - exit and init driver, as in rmmod and insmod
4841
4842 \param -
4843
4844 \return -
4845
4846 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004847static int con_mode_handler(const char *kmessage,
4848 struct kernel_param *kp)
4849{
4850 int ret = param_set_int(kmessage, kp);
4851
4852 if (ret)
4853 return ret;
4854
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004855 return fwpath_changed_handler(kmessage, kp);
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004856}
4857#endif /* #ifdef MODULE */
4858
4859/**---------------------------------------------------------------------------
4860
Jeff Johnson295189b2012-06-20 16:38:30 -07004861 \brief hdd_get_conparam() -
4862
4863 This is the driver exit point (invoked when module is unloaded using rmmod)
4864
4865 \param - None
4866
4867 \return - tVOS_CON_MODE
4868
4869 --------------------------------------------------------------------------*/
4870tVOS_CON_MODE hdd_get_conparam ( void )
4871{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004872#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07004873 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004874#else
4875 return (tVOS_CON_MODE)curr_con_mode;
4876#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004877}
4878void hdd_set_conparam ( v_UINT_t newParam )
4879{
4880 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004881#ifndef MODULE
4882 curr_con_mode = con_mode;
4883#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004884}
4885/**---------------------------------------------------------------------------
4886
4887 \brief hdd_softap_sta_deauth() - function
4888
4889 This to take counter measure to handle deauth req from HDD
4890
4891 \param - pAdapter - Pointer to the HDD
4892
4893 \param - enable - boolean value
4894
4895 \return - None
4896
4897 --------------------------------------------------------------------------*/
4898
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004899VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07004900{
Jeff Johnson295189b2012-06-20 16:38:30 -07004901 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004902 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07004903
4904 ENTER();
4905
4906 hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4907
4908 //Ignore request to deauth bcmc station
4909 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004910 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004911
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004912 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07004913
4914 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004915 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004916}
4917
4918/**---------------------------------------------------------------------------
4919
4920 \brief hdd_softap_sta_disassoc() - function
4921
4922 This to take counter measure to handle deauth req from HDD
4923
4924 \param - pAdapter - Pointer to the HDD
4925
4926 \param - enable - boolean value
4927
4928 \return - None
4929
4930 --------------------------------------------------------------------------*/
4931
4932void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
4933{
4934 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4935
4936 ENTER();
4937
4938 hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4939
4940 //Ignore request to disassoc bcmc station
4941 if( pDestMacAddress[0] & 0x1 )
4942 return;
4943
4944 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
4945}
4946
4947void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
4948{
4949 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4950
4951 ENTER();
4952
4953 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4954
4955 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
4956}
4957
Jeff Johnson295189b2012-06-20 16:38:30 -07004958/**---------------------------------------------------------------------------
4959 *
4960 * \brief hdd_get__concurrency_mode() -
4961 *
4962 *
4963 * \param - None
4964 *
4965 * \return - CONCURRENCY MODE
4966 *
4967 * --------------------------------------------------------------------------*/
4968tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
4969{
4970 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
4971 hdd_context_t *pHddCtx;
4972
4973 if (NULL != pVosContext)
4974 {
4975 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
4976 if (NULL != pHddCtx)
4977 {
4978 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
4979 }
4980 }
4981
4982 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004983 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004984 return VOS_STA;
4985}
4986
4987/* Decide whether to allow/not the apps power collapse.
4988 * Allow apps power collapse if we are in connected state.
4989 * if not, allow only if we are in IMPS */
4990v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
4991{
4992 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08004993 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07004994 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4995 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4996 hdd_adapter_t *pAdapter = NULL;
4997 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08004998 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004999
5000#ifdef WLAN_SOFTAP_FEATURE
5001 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5002 return TRUE;
5003#endif
5004
Yathish9f22e662012-12-10 14:21:35 -08005005 concurrent_state = hdd_get_concurrency_mode();
5006
5007#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5008 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
5009 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
5010 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
5011 return TRUE;
5012#endif
5013
Jeff Johnson295189b2012-06-20 16:38:30 -07005014 /*loop through all adapters. TBD fix for Concurrency */
5015 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5016 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5017 {
5018 pAdapter = pAdapterNode->pAdapter;
5019 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
5020 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5021 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005022 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07005023 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08005024 && pmcState != STOPPED && pmcState != STANDBY)) ||
5025 (eANI_BOOLEAN_TRUE == scanRspPending))
Jeff Johnson295189b2012-06-20 16:38:30 -07005026 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005027 hddLog( LOGE, "%s: do not allow APPS power collapse-"
5028 "pmcState = %d scanRspPending = %d",
5029 __func__, pmcState, scanRspPending );
Jeff Johnson295189b2012-06-20 16:38:30 -07005030 return FALSE;
5031 }
5032 }
5033 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5034 pAdapterNode = pNext;
5035 }
5036 return TRUE;
5037}
5038
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08005039/* Decides whether to send suspend notification to Riva
5040 * if any adapter is in BMPS; then it is required */
5041v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
5042{
5043 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
5044 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5045
5046 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
5047 {
5048 return TRUE;
5049 }
5050 return FALSE;
5051}
5052
Jeff Johnson295189b2012-06-20 16:38:30 -07005053void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5054{
5055 switch(mode)
5056 {
5057 case WLAN_HDD_INFRA_STATION:
5058#ifdef WLAN_FEATURE_P2P
5059 case WLAN_HDD_P2P_CLIENT:
5060 case WLAN_HDD_P2P_GO:
5061#endif
5062 case WLAN_HDD_SOFTAP:
Jeff Johnsone7245742012-09-05 17:12:55 -07005063 pHddCtx->concurrency_mode |= (1 << mode);
5064 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07005065 break;
5066 default:
5067 break;
5068
5069 }
5070 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5071 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5072}
5073
5074
5075void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5076{
5077 switch(mode)
5078 {
5079 case WLAN_HDD_INFRA_STATION:
5080#ifdef WLAN_FEATURE_P2P
5081 case WLAN_HDD_P2P_CLIENT:
5082 case WLAN_HDD_P2P_GO:
5083#endif
5084 case WLAN_HDD_SOFTAP:
5085 pHddCtx->no_of_sessions[mode]--;
5086 if (!(pHddCtx->no_of_sessions[mode]))
5087 pHddCtx->concurrency_mode &= (~(1 << mode));
5088 break;
5089 default:
5090 break;
5091 }
5092 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5093 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5094}
5095
Jeff Johnsone7245742012-09-05 17:12:55 -07005096/**---------------------------------------------------------------------------
5097 *
5098 * \brief wlan_hdd_restart_init
5099 *
5100 * This function initalizes restart timer/flag. An internal function.
5101 *
5102 * \param - pHddCtx
5103 *
5104 * \return - None
5105 *
5106 * --------------------------------------------------------------------------*/
5107
5108static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
5109{
5110 /* Initialize */
5111 pHddCtx->hdd_restart_retries = 0;
5112 atomic_set(&pHddCtx->isRestartInProgress, 0);
5113 vos_timer_init(&pHddCtx->hdd_restart_timer,
5114 VOS_TIMER_TYPE_SW,
5115 wlan_hdd_restart_timer_cb,
5116 pHddCtx);
5117}
5118/**---------------------------------------------------------------------------
5119 *
5120 * \brief wlan_hdd_restart_deinit
5121 *
5122 * This function cleans up the resources used. An internal function.
5123 *
5124 * \param - pHddCtx
5125 *
5126 * \return - None
5127 *
5128 * --------------------------------------------------------------------------*/
5129
5130static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
5131{
5132
5133 VOS_STATUS vos_status;
5134 /* Block any further calls */
5135 atomic_set(&pHddCtx->isRestartInProgress, 1);
5136 /* Cleanup */
5137 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
5138 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005139 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005140 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
5141 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005142 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005143
5144}
5145
5146/**---------------------------------------------------------------------------
5147 *
5148 * \brief wlan_hdd_framework_restart
5149 *
5150 * This function uses a cfg80211 API to start a framework initiated WLAN
5151 * driver module unload/load.
5152 *
5153 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
5154 *
5155 *
5156 * \param - pHddCtx
5157 *
5158 * \return - VOS_STATUS_SUCCESS: Success
5159 * VOS_STATUS_E_EMPTY: Adapter is Empty
5160 * VOS_STATUS_E_NOMEM: No memory
5161
5162 * --------------------------------------------------------------------------*/
5163
5164static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
5165{
5166 VOS_STATUS status = VOS_STATUS_SUCCESS;
5167 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5168 int len = (sizeof (struct ieee80211_mgmt));
5169 struct ieee80211_mgmt *mgmt = NULL;
5170
5171 /* Prepare the DEAUTH managment frame with reason code */
5172 mgmt = kzalloc(len, GFP_KERNEL);
5173 if(mgmt == NULL)
5174 {
5175 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1250df42012-12-10 14:31:52 -08005176 "%s: memory allocation failed (%d bytes)", __func__, len);
Jeff Johnsone7245742012-09-05 17:12:55 -07005177 return VOS_STATUS_E_NOMEM;
5178 }
5179 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
5180
5181 /* Iterate over all adapters/devices */
5182 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5183 do
5184 {
5185 if( (status == VOS_STATUS_SUCCESS) &&
5186 pAdapterNode &&
5187 pAdapterNode->pAdapter)
5188 {
5189 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5190 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
5191 pAdapterNode->pAdapter->dev->name,
5192 pAdapterNode->pAdapter->device_mode,
5193 pHddCtx->hdd_restart_retries + 1);
5194 /*
5195 * CFG80211 event to restart the driver
5196 *
5197 * 'cfg80211_send_unprot_deauth' sends a
5198 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
5199 * of SME(Linux Kernel) state machine.
5200 *
5201 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
5202 * the driver.
5203 *
5204 */
5205
5206 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
5207 }
5208 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5209 pAdapterNode = pNext;
5210 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
5211
5212
5213 /* Free the allocated management frame */
5214 kfree(mgmt);
5215
5216 /* Retry until we unload or reach max count */
5217 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
5218 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
5219
5220 return status;
5221
5222}
5223/**---------------------------------------------------------------------------
5224 *
5225 * \brief wlan_hdd_restart_timer_cb
5226 *
5227 * Restart timer callback. An internal function.
5228 *
5229 * \param - User data:
5230 *
5231 * \return - None
5232 *
5233 * --------------------------------------------------------------------------*/
5234
5235void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
5236{
5237 hdd_context_t *pHddCtx = usrDataForCallback;
5238 wlan_hdd_framework_restart(pHddCtx);
5239 return;
5240
5241}
5242
5243
5244/**---------------------------------------------------------------------------
5245 *
5246 * \brief wlan_hdd_restart_driver
5247 *
5248 * This function sends an event to supplicant to restart the WLAN driver.
5249 *
5250 * This function is called from vos_wlanRestart.
5251 *
5252 * \param - pHddCtx
5253 *
5254 * \return - VOS_STATUS_SUCCESS: Success
5255 * VOS_STATUS_E_EMPTY: Adapter is Empty
5256 * VOS_STATUS_E_ALREADY: Request already in progress
5257
5258 * --------------------------------------------------------------------------*/
5259VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
5260{
5261 VOS_STATUS status = VOS_STATUS_SUCCESS;
5262
5263 /* A tight check to make sure reentrancy */
5264 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
5265 {
5266 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
5267 "%s: WLAN restart is already in progress", __func__);
5268
5269 return VOS_STATUS_E_ALREADY;
5270 }
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005271 /* when WLAN driver is statically linked, then invoke SSR by sending
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005272 * the reset interrupt. If it is DLKM, then use restart API
5273 */
5274#ifdef MODULE
Jeff Johnsone7245742012-09-05 17:12:55 -07005275 status = wlan_hdd_framework_restart(pHddCtx);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005276#else
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005277#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005278 wcnss_reset_intr();
5279#endif
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005280#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005281
Jeff Johnsone7245742012-09-05 17:12:55 -07005282 return status;
5283}
5284
5285
Jeff Johnson295189b2012-06-20 16:38:30 -07005286//Register the module init/exit functions
5287module_init(hdd_module_init);
5288module_exit(hdd_module_exit);
5289
5290MODULE_LICENSE("Dual BSD/GPL");
5291MODULE_AUTHOR("Qualcomm Atheros, Inc.");
5292MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
5293
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005294module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
5295 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07005296
5297module_param_call(fwpath, fwpath_changed_handler, param_get_string, fwpath,
5298 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);