blob: 383e555471d54ec8e5caf9ecdfdbbd15da05bbb3 [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>
Jeff Johnson295189b2012-06-20 16:38:30 -0700111int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700112#include "sapApi.h"
113#include <linux/semaphore.h>
114#include <mach/subsystem_restart.h>
115#include <wlan_hdd_hostapd.h>
116#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700117#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700118#include "wlan_hdd_dev_pwr.h"
119#ifdef WLAN_BTAMP_FEATURE
120#include "bap_hdd_misc.h"
121#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700122#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700123#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800124#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530125#ifdef FEATURE_WLAN_TDLS
126#include "wlan_hdd_tdls.h"
127#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700128
129#ifdef MODULE
130#define WLAN_MODULE_NAME module_name(THIS_MODULE)
131#else
132#define WLAN_MODULE_NAME "wlan"
133#endif
134
135#ifdef TIMER_MANAGER
136#define TIMER_MANAGER_STR " +TIMER_MANAGER"
137#else
138#define TIMER_MANAGER_STR ""
139#endif
140
141#ifdef MEMORY_DEBUG
142#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
143#else
144#define MEMORY_DEBUG_STR ""
145#endif
146
147/* the Android framework expects this param even though we don't use it */
148#define BUF_LEN 20
149static char fwpath[BUF_LEN];
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700150#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700151static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700152#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700153
Jeff Johnsone7245742012-09-05 17:12:55 -0700154/*
155 * The rate at which the driver sends RESTART event to supplicant
156 * once the function 'vos_wlanRestart()' is called
157 *
158 */
159#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
160#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800161#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700162static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700163#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700164/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700165static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700166
167//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700168static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
169static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
170static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
171void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800172void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700173
Jeff Johnson295189b2012-06-20 16:38:30 -0700174v_U16_t hdd_select_queue(struct net_device *dev,
175 struct sk_buff *skb);
176
177#ifdef WLAN_FEATURE_PACKET_FILTERING
178static void hdd_set_multicast_list(struct net_device *dev);
179#endif
180
181void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
182
183extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800184#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
185void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
186static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
187static VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
188#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700189static int hdd_netdev_notifier_call(struct notifier_block * nb,
190 unsigned long state,
191 void *ndev)
192{
193 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700194 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
195 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -0700196#ifdef WLAN_BTAMP_FEATURE
197 VOS_STATUS status;
198 hdd_context_t *pHddCtx;
199#endif
200
201 //Make sure that this callback corresponds to our device.
202 if((strncmp( dev->name, "wlan", 4 )) &&
Jeff Johnsone7245742012-09-05 17:12:55 -0700203 (strncmp( dev->name, "p2p", 3))
Jeff Johnson295189b2012-06-20 16:38:30 -0700204 )
205 return NOTIFY_DONE;
206
207#ifdef CONFIG_CFG80211
208 if (!dev->ieee80211_ptr)
209 return NOTIFY_DONE;
210#endif
211
Jeff Johnson295189b2012-06-20 16:38:30 -0700212
213 if(NULL == pAdapter)
214 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800215 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700216 VOS_ASSERT(0);
217 return NOTIFY_DONE;
218 }
219
220 hddLog(VOS_TRACE_LEVEL_INFO,"%s: New Net Device State = %lu", __func__, state);
221
222 switch (state) {
223 case NETDEV_REGISTER:
224 break;
225
226 case NETDEV_UNREGISTER:
227 break;
228
229 case NETDEV_UP:
230 break;
231
232 case NETDEV_DOWN:
233 break;
234
235 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700236 if(TRUE == pAdapter->isLinkUpSvcNeeded)
237 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700238 break;
239
240 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700241 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700242 {
243 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800244 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700245 hdd_abort_mac_scan(pAdapter->pHddCtx);
246 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800247 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700248 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
249 if(!result)
250 {
251 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800252 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700253 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700254 }
255 }
256 else
257 {
258 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700259 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700260 }
261#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700262 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700263 status = WLANBAP_StopAmp();
264 if(VOS_STATUS_SUCCESS != status )
265 {
266 pHddCtx->isAmpAllowed = VOS_TRUE;
267 hddLog(VOS_TRACE_LEVEL_FATAL,
268 "%s: Failed to stop AMP", __func__);
269 }
270 else
271 {
272 //a state m/c implementation in PAL is TBD to avoid this delay
273 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700274 if ( pHddCtx->isAmpAllowed )
275 {
276 WLANBAP_DeregisterFromHCI();
277 pHddCtx->isAmpAllowed = VOS_FALSE;
278 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700279 }
280#endif //WLAN_BTAMP_FEATURE
281 break;
282
283 default:
284 break;
285 }
286
287 return NOTIFY_DONE;
288}
289
290struct notifier_block hdd_netdev_notifier = {
291 .notifier_call = hdd_netdev_notifier_call,
292};
293
294/*---------------------------------------------------------------------------
295 * Function definitions
296 *-------------------------------------------------------------------------*/
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800297int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700298void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
299void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700300//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700301static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700302#ifndef MODULE
303/* current con_mode - used only for statically linked driver
304 * con_mode is changed by userspace to indicate a mode change which will
305 * result in calling the module exit and init functions. The module
306 * exit function will clean up based on the value of con_mode prior to it
307 * being changed by userspace. So curr_con_mode records the current con_mode
308 * for exit when con_mode becomes the next mode for init
309 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700310static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700311#endif
312
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800313/**---------------------------------------------------------------------------
314
315 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
316
317 Called immediately after the cfg.ini is read in order to configure
318 the desired trace levels.
319
320 \param - moduleId - module whose trace level is being configured
321 \param - bitmask - bitmask of log levels to be enabled
322
323 \return - void
324
325 --------------------------------------------------------------------------*/
326static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
327{
328 wpt_tracelevel level;
329
330 /* if the bitmask is the default value, then a bitmask was not
331 specified in cfg.ini, so leave the logging level alone (it
332 will remain at the "compiled in" default value) */
333 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
334 {
335 return;
336 }
337
338 /* a mask was specified. start by disabling all logging */
339 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
340
341 /* now cycle through the bitmask until all "set" bits are serviced */
342 level = VOS_TRACE_LEVEL_FATAL;
343 while (0 != bitmask)
344 {
345 if (bitmask & 1)
346 {
347 vos_trace_setValue(moduleId, level, 1);
348 }
349 level++;
350 bitmask >>= 1;
351 }
352}
353
354
Jeff Johnson295189b2012-06-20 16:38:30 -0700355/**---------------------------------------------------------------------------
356
357 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
358
359 Called immediately after the cfg.ini is read in order to configure
360 the desired trace levels in the WDI.
361
362 \param - moduleId - module whose trace level is being configured
363 \param - bitmask - bitmask of log levels to be enabled
364
365 \return - void
366
367 --------------------------------------------------------------------------*/
368static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
369{
370 wpt_tracelevel level;
371
372 /* if the bitmask is the default value, then a bitmask was not
373 specified in cfg.ini, so leave the logging level alone (it
374 will remain at the "compiled in" default value) */
375 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
376 {
377 return;
378 }
379
380 /* a mask was specified. start by disabling all logging */
381 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
382
383 /* now cycle through the bitmask until all "set" bits are serviced */
384 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
385 while (0 != bitmask)
386 {
387 if (bitmask & 1)
388 {
389 wpalTraceSetLevel(moduleId, level, 1);
390 }
391 level++;
392 bitmask >>= 1;
393 }
394}
Jeff Johnson295189b2012-06-20 16:38:30 -0700395
396int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
397{
398 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
399 hdd_priv_data_t priv_data;
400 tANI_U8 *command = NULL;
401 int ret = 0;
402
403 if (NULL == pAdapter)
404 {
405 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700406 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700407 ret = -ENODEV;
408 goto exit;
409 }
410
Jeff Johnsone7245742012-09-05 17:12:55 -0700411 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700412 {
413 ret = -EINVAL;
414 goto exit;
415 }
416
417 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
418 {
419 ret = -EFAULT;
420 goto exit;
421 }
422
423 command = kmalloc(priv_data.total_len, GFP_KERNEL);
424 if (!command)
425 {
426 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700427 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700428 ret = -ENOMEM;
429 goto exit;
430 }
431
432 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
433 {
434 ret = -EFAULT;
435 goto exit;
436 }
437
438 if ((SIOCDEVPRIVATE + 1) == cmd)
439 {
440 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
441
442 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700443 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700444
445 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
446 {
447 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
448 sizeof(tSirMacAddr)))
449 {
450 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700451 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700452 ret = -EFAULT;
453 }
454 }
Amar Singhal0974e402013-02-12 14:27:46 -0800455 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700456 {
Amar Singhal0974e402013-02-12 14:27:46 -0800457 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700458 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800459
Jeff Johnson295189b2012-06-20 16:38:30 -0700460 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800461
462 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700463 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700464 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800465 "%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 -0700466 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800467 ret = hdd_setBand_helper(dev, ptr);
468 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700469 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
470 {
471 char *country_code;
472
473 country_code = command + 8;
474 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
475 pAdapter, pHddCtx->pvosContext);
476 if( 0 != ret )
477 {
478 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
479 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
480
481 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700482 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800483#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
484 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
485 {
486 tANI_U8 *value = command;
487 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
488 tANI_U8 revision = 0;
489 eHalStatus status = eHAL_STATUS_SUCCESS;
490 v_REGDOMAIN_t regId;
491
492 status = hdd_parse_countryrev(value, countryCode, &revision);
493 if (eHAL_STATUS_SUCCESS != status)
494 {
495 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
496 "%s: Failed to parse country revision information", __func__);
497 ret = -EINVAL;
498 goto exit;
499 }
500
501 /* Validate country code */
502 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
503 if (eHAL_STATUS_SUCCESS != status)
504 {
505 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
506 "%s: Invalid country code %s", __func__, countryCode);
507 ret = -EINVAL;
508 goto exit;
509 }
510
511 /* Validate revision */
512 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
513 {
514 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
515 "%s: Invalid revision %d", __func__, revision);
516 ret = -EINVAL;
517 goto exit;
518 }
519
520 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
521 pAdapter, pHddCtx->pvosContext);
522 if (0 != ret)
523 {
524 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
525 "%s: SME Change Country code fail ret=%d", __func__, ret);
526 ret = -EINVAL;
527 goto exit;
528 }
529
530 if (0 == strncmp(countryCode, "KR", 2))
531 {
532 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
533 revision);
534 if (eHAL_STATUS_SUCCESS != status)
535 {
536 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
537 "%s: Failed to build valid channel list", __func__);
538 ret = -EINVAL;
539 goto exit;
540 }
541 }
542 }
543#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700544 /*
545 command should be a string having format
546 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
547 */
Amar Singhal0974e402013-02-12 14:27:46 -0800548 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700549 {
Amar Singhal0974e402013-02-12 14:27:46 -0800550 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700551
552 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700553 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700554
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800555 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700556 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800557 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
558 {
559 int suspend = 0;
560 tANI_U8 *ptr = (tANI_U8*)command + 15;
561
562 suspend = *ptr - '0';
563 hdd_set_wlan_suspend_mode(suspend);
564 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800565#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
566 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
567 {
568 tANI_U8 *value = command;
569 int rssi = 0;
570 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
571 eHalStatus status = eHAL_STATUS_SUCCESS;
572
573 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
574 value = value + 15;
575
576 sscanf(value, "%d", &rssi);
577 lookUpThreshold = abs(rssi);
578 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
579 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
580 {
581 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
582 "Neighbor lookup threshold value %d is out of range"
583 " (Min: %d Max: %d)", lookUpThreshold,
584 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
585 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
586 ret = -EINVAL;
587 goto exit;
588 }
589
590 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
591 "%s: Received Command to Set Roam trigger"
592 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
593
594 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
595 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
596 if (eHAL_STATUS_SUCCESS != status)
597 {
598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
599 "%s: Failed to set roam trigger, try again", __func__);
600 ret = -EPERM;
601 goto exit;
602 }
603
604 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
605 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
606 }
607 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
608 {
609 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
610 int rssi = (-1) * lookUpThreshold;
611 char extra[32];
612 tANI_U8 len = 0;
613
614 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
615 if (copy_to_user(priv_data.buf, &extra, len + 1))
616 {
617 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
618 "%s: failed to copy data to user buffer", __func__);
619 ret = -EFAULT;
620 goto exit;
621 }
622 }
623 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
624 {
625 tANI_U8 *value = command;
626 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
627 /* input refresh period is in terms of seconds */
628 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
629 value = value + 18;
630 /* Convert the value from ascii to integer */
631 ret = kstrtou16(value, 10, &neighborScanRefreshPeriod);
632 if (ret < 0)
633 {
634 /* If the input value is greater than max value of datatype, then also
635 kstrtou16 fails */
636 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
637 "%s: kstrtou16 failed ",
638 "Input value may be out of range[%d - %d]",
639 __func__,
640 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
641 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
642 ret = -EINVAL;
643 goto exit;
644 }
645
646 neighborScanRefreshPeriod = neighborScanRefreshPeriod * 1000;
647 if ((neighborScanRefreshPeriod < CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN) ||
648 (neighborScanRefreshPeriod > CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX))
649 {
650 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
651 "Neighbor scan results refresh period value %d is out of range"
652 " (Min: %d Max: %d)", neighborScanRefreshPeriod,
653 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
654 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
655 ret = -EINVAL;
656 goto exit;
657 }
658
659 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
660 "%s: Received Command to Set roam scan period"
661 " (Neighbor Scan refresh period) = %d", __func__, neighborScanRefreshPeriod);
662
663 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborScanRefreshPeriod;
664 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
665 }
666 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
667 {
668 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
669 char extra[32];
670 tANI_U8 len = 0;
671
672 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
673 /* Returned value is in units of seconds */
674 if (copy_to_user(priv_data.buf, &extra, len + 1))
675 {
676 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
677 "%s: failed to copy data to user buffer", __func__);
678 ret = -EFAULT;
679 goto exit;
680 }
681 }
682#endif
683#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
684 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
685 {
686 tANI_U8 *value = command;
687 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
688
689 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
690 value = value + 13;
691 /* Convert the value from ascii to integer */
692 ret = kstrtou8(value, 10, &roamRssiDiff);
693 if (ret < 0)
694 {
695 /* If the input value is greater than max value of datatype, then also
696 kstrtou8 fails */
697 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
698 "%s: kstrtou8 failed range [%d - %d]", __func__,
699 CFG_ROAM_RSSI_DIFF_MIN,
700 CFG_ROAM_RSSI_DIFF_MAX);
701 ret = -EINVAL;
702 goto exit;
703 }
704
705 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
706 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
707 {
708 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
709 "Roam rssi diff value %d is out of range"
710 " (Min: %d Max: %d)", roamRssiDiff,
711 CFG_ROAM_RSSI_DIFF_MIN,
712 CFG_ROAM_RSSI_DIFF_MAX);
713 ret = -EINVAL;
714 goto exit;
715 }
716
717 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
718 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
719
720 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
721 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
722 }
723 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
724 {
725 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
726 char extra[32];
727 tANI_U8 len = 0;
728
729 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
730 if (copy_to_user(priv_data.buf, &extra, len + 1))
731 {
732 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
733 "%s: failed to copy data to user buffer", __func__);
734 ret = -EFAULT;
735 goto exit;
736 }
737 }
738#endif
739#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
740 else if (strncmp(command, "GETBAND", 7) == 0)
741 {
742 int band = -1;
743 char extra[32];
744 tANI_U8 len = 0;
745 hdd_getBand_helper(pHddCtx, &band);
746
747 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
748 if (copy_to_user(priv_data.buf, &extra, len + 1))
749 {
750 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
751 "%s: failed to copy data to user buffer", __func__);
752 ret = -EFAULT;
753 goto exit;
754 }
755 }
756 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
757 {
758 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
759 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
760 tANI_U8 revision = 0;
761 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
762 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
763 char extra[32] = {0};
764 tANI_U8 len = 0;
765
766 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
767 {
768 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
769 "%s: failed to get country code", __func__);
770 ret = -EFAULT;
771 goto exit;
772 }
773 pBuf[uBufLen] = '\0';
774 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
775
776 if (0 == strncmp(pBuf, "KR", 2))
777 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
778 else
779 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
780
781 if (copy_to_user(priv_data.buf, &extra, len + 1))
782 {
783 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
784 "%s: failed to copy data to user buffer", __func__);
785 ret = -EFAULT;
786 goto exit;
787 }
788 }
789 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
790 {
791 tANI_U8 *value = command;
792 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
793 tANI_U8 numChannels = 0;
794 eHalStatus status = eHAL_STATUS_SUCCESS;
795
796 status = hdd_parse_channellist(value, ChannelList, &numChannels);
797 if (eHAL_STATUS_SUCCESS != status)
798 {
799 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
800 "%s: Failed to parse channel list information", __func__);
801 ret = -EINVAL;
802 goto exit;
803 }
804
805 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
806 {
807 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
808 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
809 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
810 ret = -EINVAL;
811 goto exit;
812 }
813 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
814 numChannels);
815 if (eHAL_STATUS_SUCCESS != status)
816 {
817 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
818 "%s: Failed to update channel list information", __func__);
819 ret = -EINVAL;
820 goto exit;
821 }
822 }
823 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
824 {
825 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
826 tANI_U8 numChannels = 0;
827 tANI_U8 len = 0, j = 0;
828 char extra[128] = {0};
829
830 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
831 ChannelList, &numChannels ))
832 {
833 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
834 "%s: failed to get roam scan channel list", __func__);
835 ret = -EFAULT;
836 goto exit;
837 }
838 /* output channel list is of the format
839 [Number of roam scan channels][Channel1][Channel2]... */
840 /* copy the number of channels in the 0th index */
841 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
842 for (j = 0; (j < numChannels); j++)
843 {
844 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
845 }
846
847 if (copy_to_user(priv_data.buf, &extra, len + 1))
848 {
849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
850 "%s: failed to copy data to user buffer", __func__);
851 ret = -EFAULT;
852 goto exit;
853 }
854 }
855#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700856 else {
857 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
858 __func__, command);
859 }
860
Jeff Johnson295189b2012-06-20 16:38:30 -0700861 }
862exit:
863 if (command)
864 {
865 kfree(command);
866 }
867 return ret;
868}
869
Srinivas Girigowdade697412013-02-14 16:31:48 -0800870#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
871void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
872{
873 eCsrBand band = -1;
874 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
875 switch (band)
876 {
877 case eCSR_BAND_ALL:
878 *pBand = WLAN_HDD_UI_BAND_AUTO;
879 break;
880
881 case eCSR_BAND_24:
882 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
883 break;
884
885 case eCSR_BAND_5G:
886 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
887 break;
888
889 default:
890 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
891 *pBand = -1;
892 break;
893 }
894}
895
896/**---------------------------------------------------------------------------
897
898 \brief hdd_parse_countryrev() - HDD Parse country code revision
899
900 This function parses the country code revision passed in the format
901 SETCOUNTRYREV<space><Country code><space>revision
902
903 \param - pValue Pointer to input country code revision
904 \param - pCountryCode Pointer to local output array to record country code
905 \param - pRevision Pointer to store revision integer number
906
907 \return - 0 for success non-zero for failure
908
909 --------------------------------------------------------------------------*/
910VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
911{
912 tANI_U8 *inPtr = pValue;
913 int tempInt;
914
915 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
916 /*no argument after the command*/
917 if (NULL == inPtr)
918 {
919 return -EINVAL;
920 }
921
922 /*no space after the command*/
923 else if (SPACE_ASCII_VALUE != *inPtr)
924 {
925 return -EINVAL;
926 }
927
928 /*removing empty spaces*/
929 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
930
931 /*no argument followed by spaces*/
932 if ('\0' == *inPtr)
933 {
934 return -EINVAL;
935 }
936
937 /*getting the first argument ie the country code */
938 sscanf(inPtr, "%s ", pCountryCode);
939
940 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
941 "Country code is : %s", pCountryCode);
942
943 /*inPtr pointing to the beginning of first space after country code */
944 inPtr = strpbrk( inPtr, " " );
945 /*no revision number after the country code argument */
946 if (NULL == inPtr)
947 {
948 return -EINVAL;
949 }
950
951 inPtr++;
952
953 /*removing empty space*/
954 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
955
956 /*no channel list after the number of channels argument and spaces*/
957 if (0 == strncmp(pCountryCode, "KR", 2))
958 {
959 if ('\0' == *inPtr)
960 {
961 return -EINVAL;
962 }
963
964 sscanf(inPtr, "%d", &tempInt);
965 *pRevision = tempInt;
966 }
967 else
968 {
969 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
970 "Revision input is required only for Country KR");
971 return -EINVAL;
972 }
973 return VOS_STATUS_SUCCESS;
974}
975
976/**---------------------------------------------------------------------------
977
978 \brief hdd_parse_channellist() - HDD Parse channel list
979
980 This function parses the channel list passed in the format
981 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
982
983 \param - pValue Pointer to input channel list
984 \param - ChannelList Pointer to local output array to record channel list
985 \param - pNumChannels Pointer to number of roam scan channels
986
987 \return - 0 for success non-zero for failure
988
989 --------------------------------------------------------------------------*/
990VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
991{
992 tANI_U8 *inPtr = pValue;
993 int tempInt;
994 int j = 0;
995 int v = 0;
996 char buf[32];
997
998 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
999 /*no argument after the command*/
1000 if (NULL == inPtr)
1001 {
1002 return -EINVAL;
1003 }
1004
1005 /*no space after the command*/
1006 else if (SPACE_ASCII_VALUE != *inPtr)
1007 {
1008 return -EINVAL;
1009 }
1010
1011 /*removing empty spaces*/
1012 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
1013
1014 /*no argument followed by spaces*/
1015 if ('\0' == *inPtr)
1016 {
1017 return -EINVAL;
1018 }
1019
1020 /*getting the first argument ie the number of channels*/
1021 sscanf(inPtr, "%s ", buf);
1022 v = kstrtos32(buf, 10, &tempInt);
1023 if ( v < 0) return -EINVAL;
1024
1025 *pNumChannels = tempInt;
1026
1027 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1028 "Number of channels are: %d", *pNumChannels);
1029
1030 for (j = 0; j < (*pNumChannels); j++)
1031 {
1032 /*inPtr pointing to the beginning of first space after number of channels*/
1033 inPtr = strpbrk( inPtr, " " );
1034 /*no channel list after the number of channels argument*/
1035 if (NULL == inPtr)
1036 {
1037 return -EINVAL;
1038 }
1039
1040 /*removing empty space*/
1041 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1042
1043 /*no channel list after the number of channels argument and spaces*/
1044 if ( '\0' == *inPtr )
1045 {
1046 return -EINVAL;
1047 }
1048
1049 sscanf(inPtr, "%s ", buf);
1050 v = kstrtos32(buf, 10, &tempInt);
1051 if ( v < 0) return -EINVAL;
1052 pChannelList[j] = tempInt;
1053
1054 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1055 "Channel %d added to preferred channel list",
1056 pChannelList[j] );
1057 }
1058
1059 /* if the actual number of channels passed are more than
1060 pNumChannels then ignore the rest; take only pNumChannels */
1061 return VOS_STATUS_SUCCESS;
1062}
1063
1064#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001065/**---------------------------------------------------------------------------
1066
1067 \brief hdd_open() - HDD Open function
1068
1069 This is called in response to ifconfig up
1070
1071 \param - dev Pointer to net_device structure
1072
1073 \return - 0 for success non-zero for failure
1074
1075 --------------------------------------------------------------------------*/
1076int hdd_open (struct net_device *dev)
1077{
1078 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1079 hdd_context_t *pHddCtx;
1080 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1081 VOS_STATUS status;
1082 v_BOOL_t in_standby = TRUE;
1083
1084 if (NULL == pAdapter)
1085 {
1086 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001087 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001088 return -ENODEV;
1089 }
1090
1091 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1092 if (NULL == pHddCtx)
1093 {
1094 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001095 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001096 return -ENODEV;
1097 }
1098
1099 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1100 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1101 {
1102 if( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
1103 {
1104 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of "
1105 "standby", __func__, pAdapter->device_mode);
1106 in_standby = FALSE;
1107 break;
1108 }
1109 else
1110 {
1111 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1112 pAdapterNode = pNext;
1113 }
1114 }
1115
1116 if (TRUE == in_standby)
1117 {
1118 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
1119 {
1120 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
1121 "wlan out of power save", __func__);
1122 return -EINVAL;
1123 }
1124 }
1125
1126 pAdapter->event_flags |= DEVICE_IFACE_OPENED;
1127 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
1128 {
1129 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001130 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001131 /* Enable TX queues only when we are connected */
1132 netif_tx_start_all_queues(dev);
1133 }
1134
1135 return 0;
1136}
1137
1138int hdd_mon_open (struct net_device *dev)
1139{
1140 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1141
1142 if(pAdapter == NULL) {
1143 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001144 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001145 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001146 }
1147
1148 netif_start_queue(dev);
1149
1150 return 0;
1151}
1152/**---------------------------------------------------------------------------
1153
1154 \brief hdd_stop() - HDD stop function
1155
1156 This is called in response to ifconfig down
1157
1158 \param - dev Pointer to net_device structure
1159
1160 \return - 0 for success non-zero for failure
1161
1162 --------------------------------------------------------------------------*/
1163
1164int hdd_stop (struct net_device *dev)
1165{
1166 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1167 hdd_context_t *pHddCtx;
1168 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1169 VOS_STATUS status;
1170 v_BOOL_t enter_standby = TRUE;
1171
1172 ENTER();
1173
1174 if (NULL == pAdapter)
1175 {
1176 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001177 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001178 return -ENODEV;
1179 }
1180
1181 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1182 if (NULL == pHddCtx)
1183 {
1184 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001185 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001186 return -ENODEV;
1187 }
1188
1189 pAdapter->event_flags &= ~(DEVICE_IFACE_OPENED);
1190 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
1191 netif_tx_disable(pAdapter->dev);
1192 netif_carrier_off(pAdapter->dev);
1193
1194
1195 /* SoftAP ifaces should never go in power save mode
1196 making sure same here. */
1197 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
1198 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
1199#ifdef WLAN_FEATURE_P2P
1200 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
1201#endif
1202 )
1203 {
1204 /* SoftAP mode, so return from here */
1205 EXIT();
1206 return 0;
1207 }
1208
1209 /* Find if any iface is up then
1210 if any iface is up then can't put device to sleep/ power save mode. */
1211 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1212 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1213 {
1214 if ( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
1215 {
1216 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
1217 "put device to sleep", __func__, pAdapter->device_mode);
1218 enter_standby = FALSE;
1219 break;
1220 }
1221 else
1222 {
1223 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1224 pAdapterNode = pNext;
1225 }
1226 }
1227
1228 if (TRUE == enter_standby)
1229 {
1230 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
1231 "entering standby", __func__);
1232 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
1233 {
1234 /*log and return success*/
1235 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
1236 "wlan in power save", __func__);
1237 }
1238 }
1239
1240 EXIT();
1241 return 0;
1242}
1243
1244/**---------------------------------------------------------------------------
1245
1246 \brief hdd_uninit() - HDD uninit function
1247
1248 This is called during the netdev unregister to uninitialize all data
1249associated with the device
1250
1251 \param - dev Pointer to net_device structure
1252
1253 \return - void
1254
1255 --------------------------------------------------------------------------*/
1256static void hdd_uninit (struct net_device *dev)
1257{
1258 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1259
1260 ENTER();
1261
1262 do
1263 {
1264 if (NULL == pAdapter)
1265 {
1266 hddLog(VOS_TRACE_LEVEL_FATAL,
1267 "%s: NULL pAdapter", __func__);
1268 break;
1269 }
1270
1271 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1272 {
1273 hddLog(VOS_TRACE_LEVEL_FATAL,
1274 "%s: Invalid magic", __func__);
1275 break;
1276 }
1277
1278 if (NULL == pAdapter->pHddCtx)
1279 {
1280 hddLog(VOS_TRACE_LEVEL_FATAL,
1281 "%s: NULL pHddCtx", __func__);
1282 break;
1283 }
1284
1285 if (dev != pAdapter->dev)
1286 {
1287 hddLog(VOS_TRACE_LEVEL_FATAL,
1288 "%s: Invalid device reference", __func__);
1289 /* we haven't validated all cases so let this go for now */
1290 }
1291
1292 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
1293
1294 /* after uninit our adapter structure will no longer be valid */
1295 pAdapter->dev = NULL;
1296 pAdapter->magic = 0;
1297 } while (0);
1298
1299 EXIT();
1300}
1301
1302/**---------------------------------------------------------------------------
1303
1304 \brief hdd_release_firmware() -
1305
1306 This function calls the release firmware API to free the firmware buffer.
1307
1308 \param - pFileName Pointer to the File Name.
1309 pCtx - Pointer to the adapter .
1310
1311
1312 \return - 0 for success, non zero for failure
1313
1314 --------------------------------------------------------------------------*/
1315
1316VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
1317{
1318 VOS_STATUS status = VOS_STATUS_SUCCESS;
1319 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1320 ENTER();
1321
1322
1323 if (!strcmp(WLAN_FW_FILE, pFileName)) {
1324
1325 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
1326
1327 if(pHddCtx->fw) {
1328 release_firmware(pHddCtx->fw);
1329 pHddCtx->fw = NULL;
1330 }
1331 else
1332 status = VOS_STATUS_E_FAILURE;
1333 }
1334 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
1335 if(pHddCtx->nv) {
1336 release_firmware(pHddCtx->nv);
1337 pHddCtx->nv = NULL;
1338 }
1339 else
1340 status = VOS_STATUS_E_FAILURE;
1341
1342 }
1343
1344 EXIT();
1345 return status;
1346}
1347
1348/**---------------------------------------------------------------------------
1349
1350 \brief hdd_request_firmware() -
1351
1352 This function reads the firmware file using the request firmware
1353 API and returns the the firmware data and the firmware file size.
1354
1355 \param - pfileName - Pointer to the file name.
1356 - pCtx - Pointer to the adapter .
1357 - ppfw_data - Pointer to the pointer of the firmware data.
1358 - pSize - Pointer to the file size.
1359
1360 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
1361
1362 --------------------------------------------------------------------------*/
1363
1364
1365VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
1366{
1367 int status;
1368 VOS_STATUS retval = VOS_STATUS_SUCCESS;
1369 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1370 ENTER();
1371
1372 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
1373
1374 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
1375
1376 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1377 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
1378 __func__, pfileName);
1379 retval = VOS_STATUS_E_FAILURE;
1380 }
1381
1382 else {
1383 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
1384 *pSize = pHddCtx->fw->size;
1385 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
1386 __func__, *pSize);
1387 }
1388 }
1389 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
1390
1391 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
1392
1393 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
1394 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
1395 __func__, pfileName);
1396 retval = VOS_STATUS_E_FAILURE;
1397 }
1398
1399 else {
1400 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
1401 *pSize = pHddCtx->nv->size;
1402 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
1403 __func__, *pSize);
1404 }
1405 }
1406
1407 EXIT();
1408 return retval;
1409}
1410/**---------------------------------------------------------------------------
1411 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
1412
1413 This is the function invoked by SME to inform the result of a full power
1414 request issued by HDD
1415
1416 \param - callbackcontext - Pointer to cookie
1417 status - result of request
1418
1419 \return - None
1420
1421--------------------------------------------------------------------------*/
1422void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
1423{
1424 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
1425
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001426 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001427 if(&pHddCtx->full_pwr_comp_var)
1428 {
1429 complete(&pHddCtx->full_pwr_comp_var);
1430 }
1431}
1432
1433/**---------------------------------------------------------------------------
1434
1435 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
1436
1437 This is the function invoked by SME to inform the result of BMPS
1438 request issued by HDD
1439
1440 \param - callbackcontext - Pointer to cookie
1441 status - result of request
1442
1443 \return - None
1444
1445--------------------------------------------------------------------------*/
1446void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
1447{
1448
1449 struct completion *completion_var = (struct completion*) callbackContext;
1450
1451 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
1452 if(completion_var != NULL)
1453 {
1454 complete(completion_var);
1455 }
1456}
1457
1458/**---------------------------------------------------------------------------
1459
1460 \brief hdd_get_cfg_file_size() -
1461
1462 This function reads the configuration file using the request firmware
1463 API and returns the configuration file size.
1464
1465 \param - pCtx - Pointer to the adapter .
1466 - pFileName - Pointer to the file name.
1467 - pBufSize - Pointer to the buffer size.
1468
1469 \return - 0 for success, non zero for failure
1470
1471 --------------------------------------------------------------------------*/
1472
1473VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
1474{
1475 int status;
1476 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1477
1478 ENTER();
1479
1480 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
1481
1482 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1483 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
1484 status = VOS_STATUS_E_FAILURE;
1485 }
1486 else {
1487 *pBufSize = pHddCtx->fw->size;
1488 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
1489 release_firmware(pHddCtx->fw);
1490 pHddCtx->fw = NULL;
1491 }
1492
1493 EXIT();
1494 return VOS_STATUS_SUCCESS;
1495}
1496
1497/**---------------------------------------------------------------------------
1498
1499 \brief hdd_read_cfg_file() -
1500
1501 This function reads the configuration file using the request firmware
1502 API and returns the cfg data and the buffer size of the configuration file.
1503
1504 \param - pCtx - Pointer to the adapter .
1505 - pFileName - Pointer to the file name.
1506 - pBuffer - Pointer to the data buffer.
1507 - pBufSize - Pointer to the buffer size.
1508
1509 \return - 0 for success, non zero for failure
1510
1511 --------------------------------------------------------------------------*/
1512
1513VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
1514 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
1515{
1516 int status;
1517 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1518
1519 ENTER();
1520
1521 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
1522
1523 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1524 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
1525 return VOS_STATUS_E_FAILURE;
1526 }
1527 else {
1528 if(*pBufSize != pHddCtx->fw->size) {
1529 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
1530 "file size", __func__);
1531 release_firmware(pHddCtx->fw);
1532 pHddCtx->fw = NULL;
1533 return VOS_STATUS_E_FAILURE;
1534 }
1535 else {
1536 if(pBuffer) {
1537 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
1538 }
1539 release_firmware(pHddCtx->fw);
1540 pHddCtx->fw = NULL;
1541 }
1542 }
1543
1544 EXIT();
1545
1546 return VOS_STATUS_SUCCESS;
1547}
1548
1549/**---------------------------------------------------------------------------
1550
Jeff Johnson295189b2012-06-20 16:38:30 -07001551 \brief hdd_set_mac_address() -
1552
1553 This function sets the user specified mac address using
1554 the command ifconfig wlanX hw ether <mac adress>.
1555
1556 \param - dev - Pointer to the net device.
1557 - addr - Pointer to the sockaddr.
1558 \return - 0 for success, non zero for failure
1559
1560 --------------------------------------------------------------------------*/
1561
1562static int hdd_set_mac_address(struct net_device *dev, void *addr)
1563{
1564 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1565 struct sockaddr *psta_mac_addr = addr;
1566 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1567
1568 ENTER();
1569
1570 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
1571
1572#ifdef HDD_SESSIONIZE
1573 // set the MAC address though the STA ID CFG.
1574 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
1575 (v_U8_t *)&pAdapter->macAddressCurrent,
1576 sizeof( pAdapter->macAddressCurrent ),
1577 hdd_set_mac_addr_cb, VOS_FALSE );
1578#endif
1579
1580 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
1581
1582 EXIT();
1583 return halStatus;
1584}
1585
1586tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
1587{
1588 int i;
1589 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
1590 {
1591 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
1592 break;
1593 }
1594
1595 if( VOS_MAX_CONCURRENCY_PERSONA == i)
1596 return NULL;
1597
1598 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
1599 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
1600}
1601
1602void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
1603{
1604 int i;
1605 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
1606 {
1607 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
1608 {
1609 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
1610 break;
1611 }
1612 }
1613 return;
1614}
1615
1616#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1617 static struct net_device_ops wlan_drv_ops = {
1618 .ndo_open = hdd_open,
1619 .ndo_stop = hdd_stop,
1620 .ndo_uninit = hdd_uninit,
1621 .ndo_start_xmit = hdd_hard_start_xmit,
1622 .ndo_tx_timeout = hdd_tx_timeout,
1623 .ndo_get_stats = hdd_stats,
1624 .ndo_do_ioctl = hdd_ioctl,
1625 .ndo_set_mac_address = hdd_set_mac_address,
1626 .ndo_select_queue = hdd_select_queue,
1627#ifdef WLAN_FEATURE_PACKET_FILTERING
1628#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
1629 .ndo_set_rx_mode = hdd_set_multicast_list,
1630#else
1631 .ndo_set_multicast_list = hdd_set_multicast_list,
1632#endif //LINUX_VERSION_CODE
1633#endif
1634 };
1635#ifdef CONFIG_CFG80211
1636 static struct net_device_ops wlan_mon_drv_ops = {
1637 .ndo_open = hdd_mon_open,
1638 .ndo_stop = hdd_stop,
1639 .ndo_uninit = hdd_uninit,
1640 .ndo_start_xmit = hdd_mon_hard_start_xmit,
1641 .ndo_tx_timeout = hdd_tx_timeout,
1642 .ndo_get_stats = hdd_stats,
1643 .ndo_do_ioctl = hdd_ioctl,
1644 .ndo_set_mac_address = hdd_set_mac_address,
1645 };
1646#endif
1647
1648#endif
1649
1650void hdd_set_station_ops( struct net_device *pWlanDev )
1651{
1652#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1653 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
1654 pWlanDev->netdev_ops = &wlan_drv_ops;
1655#else
1656 pWlanDev->open = hdd_open;
1657 pWlanDev->stop = hdd_stop;
1658 pWlanDev->uninit = hdd_uninit;
1659 pWlanDev->hard_start_xmit = NULL;
1660 pWlanDev->tx_timeout = hdd_tx_timeout;
1661 pWlanDev->get_stats = hdd_stats;
1662 pWlanDev->do_ioctl = hdd_ioctl;
1663 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
1664 pWlanDev->set_mac_address = hdd_set_mac_address;
1665#endif
1666}
1667
Jeff Johnsoneed415b2013-01-18 16:11:20 -08001668static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07001669{
1670 struct net_device *pWlanDev = NULL;
1671 hdd_adapter_t *pAdapter = NULL;
1672#ifdef CONFIG_CFG80211
1673 /*
1674 * cfg80211 initialization and registration....
1675 */
1676 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
1677
1678#else
1679 //Allocate the net_device and private data (station ctx)
1680 pWlanDev = alloc_etherdev_mq(sizeof( hdd_adapter_t ), NUM_TX_QUEUES);
1681
1682#endif
1683
1684 if(pWlanDev != NULL)
1685 {
1686
1687 //Save the pointer to the net_device in the HDD adapter
1688 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
1689
1690#ifndef CONFIG_CFG80211
1691 //Init the net_device structure
1692 ether_setup(pWlanDev);
1693#endif
1694
1695 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
1696
1697 pAdapter->dev = pWlanDev;
1698 pAdapter->pHddCtx = pHddCtx;
1699 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
1700
1701 init_completion(&pAdapter->session_open_comp_var);
1702 init_completion(&pAdapter->session_close_comp_var);
1703 init_completion(&pAdapter->disconnect_comp_var);
1704 init_completion(&pAdapter->linkup_event_var);
1705 init_completion(&pAdapter->cancel_rem_on_chan_var);
1706 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001707#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1708 init_completion(&pAdapter->offchannel_tx_event);
1709#endif
1710#ifdef CONFIG_CFG80211
1711 init_completion(&pAdapter->tx_action_cnf_event);
1712#endif
Hoonki Lee11f7dda2013-02-14 16:55:44 -08001713#ifdef FEATURE_WLAN_TDLS
1714 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001715 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08001716#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001717 init_completion(&pHddCtx->mc_sus_event_var);
1718 init_completion(&pHddCtx->tx_sus_event_var);
1719
Jeff Johnson295189b2012-06-20 16:38:30 -07001720 pAdapter->isLinkUpSvcNeeded = FALSE;
1721 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
1722 //Init the net_device structure
1723 strlcpy(pWlanDev->name, name, IFNAMSIZ);
1724
1725 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
1726 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
1727 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
1728 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
1729
1730 hdd_set_station_ops( pAdapter->dev );
1731
1732 pWlanDev->destructor = free_netdev;
1733#ifdef CONFIG_CFG80211
1734 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
1735 pAdapter->wdev.wiphy = pHddCtx->wiphy;
1736 pAdapter->wdev.netdev = pWlanDev;
1737#endif
1738 /* set pWlanDev's parent to underlying device */
1739 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
1740 }
1741
1742 return pAdapter;
1743}
1744
1745VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
1746{
1747 struct net_device *pWlanDev = pAdapter->dev;
1748 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1749 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1750 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1751
1752 if( rtnl_lock_held )
1753 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001754 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07001755 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
1756 {
1757 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
1758 return VOS_STATUS_E_FAILURE;
1759 }
1760 }
1761 if (register_netdevice(pWlanDev))
1762 {
1763 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
1764 return VOS_STATUS_E_FAILURE;
1765 }
1766 }
1767 else
1768 {
1769 if(register_netdev(pWlanDev))
1770 {
1771 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
1772 return VOS_STATUS_E_FAILURE;
1773 }
1774 }
1775 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
1776
1777 return VOS_STATUS_SUCCESS;
1778}
1779
1780eHalStatus hdd_smeCloseSessionCallback(void *pContext)
1781{
1782 if(pContext != NULL)
1783 {
1784 clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags);
1785
1786 /* need to make sure all of our scheduled work has completed.
1787 * This callback is called from MC thread context, so it is safe to
1788 * to call below flush workqueue API from here.
1789 */
1790 flush_scheduled_work();
1791 complete(&((hdd_adapter_t*)pContext)->session_close_comp_var);
1792 }
1793 return eHAL_STATUS_SUCCESS;
1794}
1795
1796VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
1797{
1798 struct net_device *pWlanDev = pAdapter->dev;
1799 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1800 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1801 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1802 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1803 int rc = 0;
1804
1805 INIT_COMPLETION(pAdapter->session_open_comp_var);
1806 //Open a SME session for future operation
1807 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
1808 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
1809 if ( !HAL_STATUS_SUCCESS( halStatus ) )
1810 {
1811 hddLog(VOS_TRACE_LEVEL_FATAL,
1812 "sme_OpenSession() failed with status code %08d [x%08lx]",
1813 halStatus, halStatus );
1814 status = VOS_STATUS_E_FAILURE;
1815 goto error_sme_open;
1816 }
1817
1818 //Block on a completion variable. Can't wait forever though.
1819 rc = wait_for_completion_interruptible_timeout(
1820 &pAdapter->session_open_comp_var,
1821 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1822 if (!rc)
1823 {
1824 hddLog(VOS_TRACE_LEVEL_FATAL,
1825 "Session is not opened within timeout period code %08d", rc );
1826 status = VOS_STATUS_E_FAILURE;
1827 goto error_sme_open;
1828 }
1829
1830 // Register wireless extensions
1831 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
1832 {
1833 hddLog(VOS_TRACE_LEVEL_FATAL,
1834 "hdd_register_wext() failed with status code %08d [x%08lx]",
1835 halStatus, halStatus );
1836 status = VOS_STATUS_E_FAILURE;
1837 goto error_register_wext;
1838 }
1839 //Safe to register the hard_start_xmit function again
1840#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1841 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
1842#else
1843 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
1844#endif
1845
1846 //Set the Connection State to Not Connected
1847 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
1848
1849 //Set the default operation channel
1850 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
1851
1852 /* Make the default Auth Type as OPEN*/
1853 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
1854
1855 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
1856 {
1857 hddLog(VOS_TRACE_LEVEL_FATAL,
1858 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
1859 status, status );
1860 goto error_init_txrx;
1861 }
1862
1863 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1864
1865 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
1866 {
1867 hddLog(VOS_TRACE_LEVEL_FATAL,
1868 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
1869 status, status );
1870 goto error_wmm_init;
1871 }
1872
1873 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1874
1875 return VOS_STATUS_SUCCESS;
1876
1877error_wmm_init:
1878 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1879 hdd_deinit_tx_rx(pAdapter);
1880error_init_txrx:
1881 hdd_UnregisterWext(pWlanDev);
1882error_register_wext:
1883 if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
1884 {
1885 INIT_COMPLETION(pAdapter->session_close_comp_var);
1886 if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
1887 pAdapter->sessionId,
1888 hdd_smeCloseSessionCallback, pAdapter ) )
1889 {
1890 //Block on a completion variable. Can't wait forever though.
1891 wait_for_completion_interruptible_timeout(
1892 &pAdapter->session_close_comp_var,
1893 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1894 }
1895}
1896error_sme_open:
1897 return status;
1898}
1899
Jeff Johnson295189b2012-06-20 16:38:30 -07001900#ifdef CONFIG_CFG80211
1901void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1902{
1903 hdd_cfg80211_state_t *cfgState;
1904
1905 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1906
1907 if( NULL != cfgState->buf )
1908 {
1909 int rc;
1910 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
1911 rc = wait_for_completion_interruptible_timeout(
1912 &pAdapter->tx_action_cnf_event,
1913 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
1914 if(!rc)
1915 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08001916 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001917 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
1918 }
1919 }
1920 return;
1921}
1922#endif
1923
1924void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1925{
1926 ENTER();
1927 switch ( pAdapter->device_mode )
1928 {
1929 case WLAN_HDD_INFRA_STATION:
1930 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07001931 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07001932 {
1933 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1934 {
1935 hdd_deinit_tx_rx( pAdapter );
1936 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1937 }
1938
1939 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
1940 {
1941 hdd_wmm_adapter_close( pAdapter );
1942 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1943 }
1944
1945#ifdef CONFIG_CFG80211
1946 hdd_cleanup_actionframe(pHddCtx, pAdapter);
1947#endif
1948
1949 break;
1950 }
1951
1952 case WLAN_HDD_SOFTAP:
1953 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07001954 {
1955#ifdef CONFIG_CFG80211
1956 hdd_cleanup_actionframe(pHddCtx, pAdapter);
1957#endif
1958
1959 hdd_unregister_hostapd(pAdapter);
1960 hdd_set_conparam( 0 );
1961#ifdef CONFIG_CFG80211
1962 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
1963#endif
1964 break;
1965 }
1966
1967 case WLAN_HDD_MONITOR:
1968 {
1969#ifdef CONFIG_CFG80211
1970 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
1971#endif
1972 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1973 {
1974 hdd_deinit_tx_rx( pAdapter );
1975 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1976 }
1977#ifdef CONFIG_CFG80211
1978 if(NULL != pAdapterforTx)
1979 {
1980 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
1981 }
1982#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001983 break;
1984 }
1985
1986
1987 default:
1988 break;
1989 }
1990
1991 EXIT();
1992}
1993
1994void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
1995{
1996 struct net_device *pWlanDev = pAdapter->dev;
1997
1998 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
1999 if( rtnl_held )
2000 {
2001 unregister_netdevice(pWlanDev);
2002 }
2003 else
2004 {
2005 unregister_netdev(pWlanDev);
2006 }
2007 // note that the pAdapter is no longer valid at this point
2008 // since the memory has been reclaimed
2009 }
2010
2011}
2012
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08002013void hdd_set_pwrparams(hdd_context_t *pHddCtx)
2014{
2015 tSirSetPowerParamsReq powerRequest = { 0 };
2016
2017 powerRequest.uIgnoreDTIM = 1;
2018
2019 if (pHddCtx->cfg_ini->enableModulatedDTIM)
2020 {
2021 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
2022 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2023 }
2024 else
2025 {
2026 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
2027 }
2028
2029 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
2030 *specified during Enter/Exit BMPS when LCD off*/
2031 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2032 NULL, eANI_BOOLEAN_FALSE);
2033 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2034 NULL, eANI_BOOLEAN_FALSE);
2035
2036 /* switch to the DTIM specified in cfg.ini */
2037 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2038 "Switch to DTIM%d", powerRequest.uListenInterval);
2039 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2040
2041}
2042
2043void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
2044{
2045 /*Switch back to DTIM 1*/
2046 tSirSetPowerParamsReq powerRequest = { 0 };
2047
2048 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
2049 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2050
2051 /* Update ignoreDTIM and ListedInterval in CFG with default values */
2052 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2053 NULL, eANI_BOOLEAN_FALSE);
2054 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2055 NULL, eANI_BOOLEAN_FALSE);
2056
2057 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2058 "Switch to DTIM%d",powerRequest.uListenInterval);
2059 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2060
2061}
2062
Jeff Johnson295189b2012-06-20 16:38:30 -07002063VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
2064{
2065 VOS_STATUS status = VOS_STATUS_SUCCESS;
2066
2067 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2068 {
2069 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2070 }
2071
2072 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2073 {
2074 sme_StartAutoBmpsTimer(pHddCtx->hHal);
2075 }
2076
2077 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2078 {
2079 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2080 }
2081
2082 return status;
2083}
2084
2085VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
2086{
2087 hdd_adapter_t *pAdapter = NULL;
2088 eHalStatus halStatus;
2089 VOS_STATUS status = VOS_STATUS_E_INVAL;
2090 v_BOOL_t disableBmps = FALSE;
2091 v_BOOL_t disableImps = FALSE;
2092
2093 switch(session_type)
2094 {
2095 case WLAN_HDD_INFRA_STATION:
2096 case WLAN_HDD_SOFTAP:
2097#ifdef WLAN_FEATURE_P2P
2098 case WLAN_HDD_P2P_CLIENT:
2099 case WLAN_HDD_P2P_GO:
2100#endif
2101 //Exit BMPS -> Is Sta/P2P Client is already connected
2102 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
2103 if((NULL != pAdapter)&&
2104 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2105 {
2106 disableBmps = TRUE;
2107 }
2108
2109 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
2110 if((NULL != pAdapter)&&
2111 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2112 {
2113 disableBmps = TRUE;
2114 }
2115
2116 //Exit both Bmps and Imps incase of Go/SAP Mode
2117 if((WLAN_HDD_SOFTAP == session_type) ||
2118 (WLAN_HDD_P2P_GO == session_type))
2119 {
2120 disableBmps = TRUE;
2121 disableImps = TRUE;
2122 }
2123
2124 if(TRUE == disableImps)
2125 {
2126 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2127 {
2128 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2129 }
2130 }
2131
2132 if(TRUE == disableBmps)
2133 {
2134 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2135 {
2136 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2137
2138 if(eHAL_STATUS_SUCCESS != halStatus)
2139 {
2140 status = VOS_STATUS_E_FAILURE;
2141 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
2142 VOS_ASSERT(0);
2143 return status;
2144 }
2145 }
2146
2147 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2148 {
2149 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
2150
2151 if(eHAL_STATUS_SUCCESS != halStatus)
2152 {
2153 status = VOS_STATUS_E_FAILURE;
2154 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
2155 VOS_ASSERT(0);
2156 return status;
2157 }
2158 }
2159 }
2160
2161 if((TRUE == disableBmps) ||
2162 (TRUE == disableImps))
2163 {
2164 /* Now, get the chip into Full Power now */
2165 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
2166 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
2167 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
2168
2169 if(halStatus != eHAL_STATUS_SUCCESS)
2170 {
2171 if(halStatus == eHAL_STATUS_PMC_PENDING)
2172 {
2173 //Block on a completion variable. Can't wait forever though
2174 wait_for_completion_interruptible_timeout(
2175 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
2176 }
2177 else
2178 {
2179 status = VOS_STATUS_E_FAILURE;
2180 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
2181 VOS_ASSERT(0);
2182 return status;
2183 }
2184 }
2185
2186 status = VOS_STATUS_SUCCESS;
2187 }
2188
2189 break;
2190 }
2191 return status;
2192}
2193
2194hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002195 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07002196 tANI_U8 rtnl_held )
2197{
2198 hdd_adapter_t *pAdapter = NULL;
2199 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
2200 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2201 VOS_STATUS exitbmpsStatus;
2202
2203 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
2204
2205 //Disable BMPS incase of Concurrency
2206 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
2207
2208 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
2209 {
2210 //Fail to Exit BMPS
2211 VOS_ASSERT(0);
2212 return NULL;
2213 }
2214
2215 switch(session_type)
2216 {
2217 case WLAN_HDD_INFRA_STATION:
2218#ifdef WLAN_FEATURE_P2P
2219 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002220 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002221#endif
2222 {
2223 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2224
2225 if( NULL == pAdapter )
2226 return NULL;
2227
2228#ifdef CONFIG_CFG80211
Jeff Johnsone7245742012-09-05 17:12:55 -07002229 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
2230 NL80211_IFTYPE_P2P_CLIENT:
2231 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07002232#endif
2233
Jeff Johnson295189b2012-06-20 16:38:30 -07002234 pAdapter->device_mode = session_type;
2235
2236 status = hdd_init_station_mode( pAdapter );
2237 if( VOS_STATUS_SUCCESS != status )
2238 goto err_free_netdev;
2239
2240 status = hdd_register_interface( pAdapter, rtnl_held );
2241 if( VOS_STATUS_SUCCESS != status )
2242 {
2243 hdd_deinit_adapter(pHddCtx, pAdapter);
2244 goto err_free_netdev;
2245 }
2246 //Stop the Interface TX queue.
2247 netif_tx_disable(pAdapter->dev);
2248 //netif_tx_disable(pWlanDev);
2249 netif_carrier_off(pAdapter->dev);
2250
2251 break;
2252 }
2253
2254#ifdef WLAN_FEATURE_P2P
2255 case WLAN_HDD_P2P_GO:
2256#endif
2257 case WLAN_HDD_SOFTAP:
2258 {
2259 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
2260 if( NULL == pAdapter )
2261 return NULL;
2262
2263#ifdef CONFIG_CFG80211
2264 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
2265 NL80211_IFTYPE_AP:
2266 NL80211_IFTYPE_P2P_GO;
2267#endif
2268 pAdapter->device_mode = session_type;
2269
2270 status = hdd_init_ap_mode(pAdapter);
2271 if( VOS_STATUS_SUCCESS != status )
2272 goto err_free_netdev;
2273
2274 status = hdd_register_hostapd( pAdapter, rtnl_held );
2275 if( VOS_STATUS_SUCCESS != status )
2276 {
2277 hdd_deinit_adapter(pHddCtx, pAdapter);
2278 goto err_free_netdev;
2279 }
2280
2281 netif_tx_disable(pAdapter->dev);
2282 netif_carrier_off(pAdapter->dev);
2283
2284 hdd_set_conparam( 1 );
2285 break;
2286 }
2287 case WLAN_HDD_MONITOR:
2288 {
2289#ifdef CONFIG_CFG80211
2290 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2291 if( NULL == pAdapter )
2292 return NULL;
2293
2294 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
2295 pAdapter->device_mode = session_type;
2296 status = hdd_register_interface( pAdapter, rtnl_held );
2297#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
2298 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
2299#else
2300 pAdapter->dev->open = hdd_mon_open;
2301 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
2302#endif
2303 hdd_init_tx_rx( pAdapter );
2304 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2305 //Set adapter to be used for data tx. It will use either GO or softap.
2306 pAdapter->sessionCtx.monitor.pAdapterForTx =
2307 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
2308#ifdef WLAN_FEATURE_P2P
2309 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
2310 {
2311 pAdapter->sessionCtx.monitor.pAdapterForTx =
2312 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
2313 }
2314#endif
2315 /* This workqueue will be used to transmit management packet over
2316 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07002317 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
2318 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
2319 return NULL;
2320 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07002321
Jeff Johnson295189b2012-06-20 16:38:30 -07002322 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
2323 hdd_mon_tx_work_queue);
2324#endif
2325 }
2326 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002327 case WLAN_HDD_FTM:
2328 {
2329 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2330
2331 if( NULL == pAdapter )
2332 return NULL;
2333 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
2334 * message while loading driver in FTM mode. */
2335 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
2336 pAdapter->device_mode = session_type;
2337 status = hdd_register_interface( pAdapter, rtnl_held );
2338 }
2339 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002340 default:
2341 {
2342 VOS_ASSERT(0);
2343 return NULL;
2344 }
2345 }
2346
2347
2348 if( VOS_STATUS_SUCCESS == status )
2349 {
2350 //Add it to the hdd's session list.
2351 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
2352 if( NULL == pHddAdapterNode )
2353 {
2354 status = VOS_STATUS_E_NOMEM;
2355 }
2356 else
2357 {
2358 pHddAdapterNode->pAdapter = pAdapter;
2359 status = hdd_add_adapter_back ( pHddCtx,
2360 pHddAdapterNode );
2361 }
2362 }
2363
2364 if( VOS_STATUS_SUCCESS != status )
2365 {
2366 if( NULL != pAdapter )
2367 {
2368 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
2369 pAdapter = NULL;
2370 }
2371 if( NULL != pHddAdapterNode )
2372 {
2373 vos_mem_free( pHddAdapterNode );
2374 }
2375
2376 goto resume_bmps;
2377 }
2378
2379 if(VOS_STATUS_SUCCESS == status)
2380 {
2381 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
2382
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07002383 //Initialize the WoWL service
2384 if(!hdd_init_wowl(pAdapter))
2385 {
2386 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
2387 goto err_free_netdev;
2388 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002389 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002390 return pAdapter;
2391
2392err_free_netdev:
2393 free_netdev(pAdapter->dev);
2394 wlan_hdd_release_intf_addr( pHddCtx,
2395 pAdapter->macAddressCurrent.bytes );
2396
2397resume_bmps:
2398 //If bmps disabled enable it
2399 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
2400 {
2401 hdd_enable_bmps_imps(pHddCtx);
2402 }
2403 return NULL;
2404}
2405
2406VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
2407 tANI_U8 rtnl_held )
2408{
2409 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
2410 VOS_STATUS status;
2411
2412 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
2413 if( VOS_STATUS_SUCCESS != status )
2414 return status;
2415
2416 while ( pCurrent->pAdapter != pAdapter )
2417 {
2418 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
2419 if( VOS_STATUS_SUCCESS != status )
2420 break;
2421
2422 pCurrent = pNext;
2423 }
2424 pAdapterNode = pCurrent;
2425 if( VOS_STATUS_SUCCESS == status )
2426 {
2427 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2428 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
2429 hdd_remove_adapter( pHddCtx, pAdapterNode );
2430 vos_mem_free( pAdapterNode );
2431
Jeff Johnson295189b2012-06-20 16:38:30 -07002432
2433 /* If there is a single session of STA/P2P client, re-enable BMPS */
2434 if ((!vos_concurrent_sessions_running()) &&
2435 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
2436 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
2437 {
2438 hdd_enable_bmps_imps(pHddCtx);
2439 }
2440
2441 return VOS_STATUS_SUCCESS;
2442 }
2443
2444 return VOS_STATUS_E_FAILURE;
2445}
2446
2447VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
2448{
2449 hdd_adapter_list_node_t *pHddAdapterNode;
2450 VOS_STATUS status;
2451
2452 ENTER();
2453
2454 do
2455 {
2456 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
2457 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
2458 {
2459 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
2460 vos_mem_free( pHddAdapterNode );
2461 }
2462 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
2463
2464 EXIT();
2465
2466 return VOS_STATUS_SUCCESS;
2467}
2468
2469void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
2470{
2471 v_U8_t addIE[1] = {0};
2472
2473 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2474 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
2475 eANI_BOOLEAN_FALSE) )
2476 {
2477 hddLog(LOGE,
2478 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
2479 }
2480
2481 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2482 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
2483 eANI_BOOLEAN_FALSE) )
2484 {
2485 hddLog(LOGE,
2486 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
2487 }
2488
2489 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2490 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
2491 eANI_BOOLEAN_FALSE) )
2492 {
2493 hddLog(LOGE,
2494 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
2495 }
2496}
2497
2498VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2499{
2500 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2501 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2502 union iwreq_data wrqu;
2503
2504 ENTER();
2505
2506 switch(pAdapter->device_mode)
2507 {
2508 case WLAN_HDD_INFRA_STATION:
2509 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002510 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002511 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
2512 {
2513 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
2514 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
2515 pAdapter->sessionId,
2516 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
2517 else
2518 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
2519 pAdapter->sessionId,
2520 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2521 //success implies disconnect command got queued up successfully
2522 if(halStatus == eHAL_STATUS_SUCCESS)
2523 {
2524 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
2525 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2526 }
2527 memset(&wrqu, '\0', sizeof(wrqu));
2528 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2529 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2530 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2531 }
2532 else
2533 {
2534 hdd_abort_mac_scan(pHddCtx);
2535 }
2536
2537 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
2538 {
2539 INIT_COMPLETION(pAdapter->session_close_comp_var);
2540 if (eHAL_STATUS_SUCCESS ==
2541 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
2542 hdd_smeCloseSessionCallback, pAdapter))
2543 {
2544 //Block on a completion variable. Can't wait forever though.
2545 wait_for_completion_interruptible_timeout(
2546 &pAdapter->session_close_comp_var,
2547 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2548 }
2549 }
2550
2551 break;
2552
2553 case WLAN_HDD_SOFTAP:
2554 case WLAN_HDD_P2P_GO:
2555 //Any softap specific cleanup here...
2556 mutex_lock(&pHddCtx->sap_lock);
2557 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2558 {
2559 VOS_STATUS status;
2560 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2561
2562 //Stop Bss.
2563 status = WLANSAP_StopBss(pHddCtx->pvosContext);
2564 if (VOS_IS_STATUS_SUCCESS(status))
2565 {
2566 hdd_hostapd_state_t *pHostapdState =
2567 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2568
2569 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2570
2571 if (!VOS_IS_STATUS_SUCCESS(status))
2572 {
2573 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002574 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002575 }
2576 }
2577 else
2578 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002579 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002580 }
2581 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2582
2583 if (eHAL_STATUS_FAILURE ==
2584 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
2585 0, NULL, eANI_BOOLEAN_FALSE))
2586 {
2587 hddLog(LOGE,
2588 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002589 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002590 }
2591
2592 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2593 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2594 eANI_BOOLEAN_FALSE) )
2595 {
2596 hddLog(LOGE,
2597 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
2598 }
2599
2600 // Reset WNI_CFG_PROBE_RSP Flags
2601 wlan_hdd_reset_prob_rspies(pAdapter);
2602 kfree(pAdapter->sessionCtx.ap.beacon);
2603 pAdapter->sessionCtx.ap.beacon = NULL;
2604 }
2605 mutex_unlock(&pHddCtx->sap_lock);
2606 break;
2607 case WLAN_HDD_MONITOR:
2608 break;
2609 default:
2610 break;
2611 }
2612
2613 EXIT();
2614 return VOS_STATUS_SUCCESS;
2615}
2616
2617VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
2618{
2619 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2620 VOS_STATUS status;
2621 hdd_adapter_t *pAdapter;
2622
2623 ENTER();
2624
2625 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2626
2627 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2628 {
2629 pAdapter = pAdapterNode->pAdapter;
2630 netif_tx_disable(pAdapter->dev);
2631 netif_carrier_off(pAdapter->dev);
2632
2633 hdd_stop_adapter( pHddCtx, pAdapter );
2634
2635 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2636 pAdapterNode = pNext;
2637 }
2638
2639 EXIT();
2640
2641 return VOS_STATUS_SUCCESS;
2642}
2643
2644VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
2645{
2646 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2647 VOS_STATUS status;
2648 hdd_adapter_t *pAdapter;
2649
2650 ENTER();
2651
2652 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2653
2654 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2655 {
2656 pAdapter = pAdapterNode->pAdapter;
2657 netif_tx_disable(pAdapter->dev);
2658 netif_carrier_off(pAdapter->dev);
2659
2660 //Record whether STA is associated
2661 pAdapter->sessionCtx.station.bSendDisconnect =
2662 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
2663 VOS_TRUE : VOS_FALSE;
2664
2665 hdd_deinit_tx_rx(pAdapter);
2666 hdd_wmm_adapter_close(pAdapter);
2667
2668 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2669 pAdapterNode = pNext;
2670 }
2671
2672 EXIT();
2673
2674 return VOS_STATUS_SUCCESS;
2675}
2676
2677VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
2678{
2679 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2680 VOS_STATUS status;
2681 hdd_adapter_t *pAdapter;
2682 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
2683
2684 ENTER();
2685
2686 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2687
2688 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2689 {
2690 pAdapter = pAdapterNode->pAdapter;
2691
2692 switch(pAdapter->device_mode)
2693 {
2694 case WLAN_HDD_INFRA_STATION:
2695 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002696 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002697 hdd_init_station_mode(pAdapter);
2698 /* Open the gates for HDD to receive Wext commands */
2699 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002700 pHddCtx->scan_info.mScanPending = FALSE;
2701 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002702
2703 //Trigger the initial scan
2704 hdd_wlan_initial_scan(pAdapter);
2705
2706 //Indicate disconnect event to supplicant if associated previously
2707 if(pAdapter->sessionCtx.station.bSendDisconnect)
2708 {
2709 union iwreq_data wrqu;
2710 memset(&wrqu, '\0', sizeof(wrqu));
2711 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2712 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2713 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2714 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
2715
2716#ifdef CONFIG_CFG80211
2717 /* indicate disconnected event to nl80211 */
2718 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
2719 NULL, 0, GFP_KERNEL);
2720#endif
2721 }
2722 break;
2723
2724 case WLAN_HDD_SOFTAP:
2725 /* softAP can handle SSR */
2726 break;
2727
2728 case WLAN_HDD_P2P_GO:
2729#ifdef CONFIG_CFG80211
2730 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
2731 __func__);
2732 /* event supplicant to restart */
2733 cfg80211_del_sta(pAdapter->dev,
2734 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
2735#endif
2736 break;
2737
2738 case WLAN_HDD_MONITOR:
2739 /* monitor interface start */
2740 break;
2741 default:
2742 break;
2743 }
2744
2745 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2746 pAdapterNode = pNext;
2747 }
2748
2749 EXIT();
2750
2751 return VOS_STATUS_SUCCESS;
2752}
2753
2754VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
2755{
2756 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2757 hdd_adapter_t *pAdapter;
2758 VOS_STATUS status;
2759 v_U32_t roamId;
2760
2761 ENTER();
2762
2763 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2764
2765 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2766 {
2767 pAdapter = pAdapterNode->pAdapter;
2768
2769 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
2770 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
2771 {
2772 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2773 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2774
2775 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2776 init_completion(&pAdapter->disconnect_comp_var);
2777 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
2778 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2779
2780 wait_for_completion_interruptible_timeout(
2781 &pAdapter->disconnect_comp_var,
2782 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2783
2784 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
2785 pHddCtx->isAmpAllowed = VOS_FALSE;
2786 sme_RoamConnect(pHddCtx->hHal,
2787 pAdapter->sessionId, &(pWextState->roamProfile),
2788 &roamId);
2789 }
2790
2791 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2792 pAdapterNode = pNext;
2793 }
2794
2795 EXIT();
2796
2797 return VOS_STATUS_SUCCESS;
2798}
2799
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002800bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07002801{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002802 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07002803}
2804
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002805/* Once SSR is disabled then it cannot be set. */
2806void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07002807{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002808 if (HDD_SSR_DISABLED == isSsrRequired)
2809 return;
2810
Jeff Johnson295189b2012-06-20 16:38:30 -07002811 isSsrRequired = value;
2812}
2813
2814VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
2815 hdd_adapter_list_node_t** ppAdapterNode)
2816{
2817 VOS_STATUS status;
2818 spin_lock(&pHddCtx->hddAdapters.lock);
2819 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
2820 (hdd_list_node_t**) ppAdapterNode );
2821 spin_unlock(&pHddCtx->hddAdapters.lock);
2822 return status;
2823}
2824
2825VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
2826 hdd_adapter_list_node_t* pAdapterNode,
2827 hdd_adapter_list_node_t** pNextAdapterNode)
2828{
2829 VOS_STATUS status;
2830 spin_lock(&pHddCtx->hddAdapters.lock);
2831 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
2832 (hdd_list_node_t*) pAdapterNode,
2833 (hdd_list_node_t**)pNextAdapterNode );
2834
2835 spin_unlock(&pHddCtx->hddAdapters.lock);
2836 return status;
2837}
2838
2839VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
2840 hdd_adapter_list_node_t* pAdapterNode)
2841{
2842 VOS_STATUS status;
2843 spin_lock(&pHddCtx->hddAdapters.lock);
2844 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
2845 &pAdapterNode->node );
2846 spin_unlock(&pHddCtx->hddAdapters.lock);
2847 return status;
2848}
2849
2850VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
2851 hdd_adapter_list_node_t** ppAdapterNode)
2852{
2853 VOS_STATUS status;
2854 spin_lock(&pHddCtx->hddAdapters.lock);
2855 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
2856 (hdd_list_node_t**) ppAdapterNode );
2857 spin_unlock(&pHddCtx->hddAdapters.lock);
2858 return status;
2859}
2860
2861VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
2862 hdd_adapter_list_node_t* pAdapterNode)
2863{
2864 VOS_STATUS status;
2865 spin_lock(&pHddCtx->hddAdapters.lock);
2866 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
2867 (hdd_list_node_t*) pAdapterNode );
2868 spin_unlock(&pHddCtx->hddAdapters.lock);
2869 return status;
2870}
2871
2872VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
2873 hdd_adapter_list_node_t* pAdapterNode)
2874{
2875 VOS_STATUS status;
2876 spin_lock(&pHddCtx->hddAdapters.lock);
2877 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
2878 (hdd_list_node_t*) pAdapterNode );
2879 spin_unlock(&pHddCtx->hddAdapters.lock);
2880 return status;
2881}
2882
2883hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
2884 tSirMacAddr macAddr )
2885{
2886 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2887 hdd_adapter_t *pAdapter;
2888 VOS_STATUS status;
2889
2890 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2891
2892 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2893 {
2894 pAdapter = pAdapterNode->pAdapter;
2895
2896 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
2897 macAddr, sizeof(tSirMacAddr) ) )
2898 {
2899 return pAdapter;
2900 }
2901 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2902 pAdapterNode = pNext;
2903 }
2904
2905 return NULL;
2906
2907}
2908
2909hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
2910{
2911 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2912 hdd_adapter_t *pAdapter;
2913 VOS_STATUS status;
2914
2915 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2916
2917 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2918 {
2919 pAdapter = pAdapterNode->pAdapter;
2920
2921 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
2922 IFNAMSIZ ) )
2923 {
2924 return pAdapter;
2925 }
2926 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2927 pAdapterNode = pNext;
2928 }
2929
2930 return NULL;
2931
2932}
2933
2934hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
2935{
2936 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2937 hdd_adapter_t *pAdapter;
2938 VOS_STATUS status;
2939
2940 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2941
2942 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2943 {
2944 pAdapter = pAdapterNode->pAdapter;
2945
2946 if( pAdapter && (mode == pAdapter->device_mode) )
2947 {
2948 return pAdapter;
2949 }
2950 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2951 pAdapterNode = pNext;
2952 }
2953
2954 return NULL;
2955
2956}
2957
2958//Remove this function later
2959hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
2960{
2961 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2962 hdd_adapter_t *pAdapter;
2963 VOS_STATUS status;
2964
2965 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2966
2967 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2968 {
2969 pAdapter = pAdapterNode->pAdapter;
2970
2971 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
2972 {
2973 return pAdapter;
2974 }
2975
2976 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2977 pAdapterNode = pNext;
2978 }
2979
2980 return NULL;
2981
2982}
2983
2984#ifdef CONFIG_CFG80211
2985/**---------------------------------------------------------------------------
2986
2987 \brief hdd_set_monitor_tx_adapter() -
2988
2989 This API initializes the adapter to be used while transmitting on monitor
2990 adapter.
2991
2992 \param - pHddCtx - Pointer to the HDD context.
2993 pAdapter - Adapter that will used for TX. This can be NULL.
2994 \return - None.
2995 --------------------------------------------------------------------------*/
2996void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2997{
2998 hdd_adapter_t *pMonAdapter;
2999
3000 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
3001
3002 if( NULL != pMonAdapter )
3003 {
3004 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
3005 }
3006}
3007#endif
3008/**---------------------------------------------------------------------------
3009
3010 \brief hdd_select_queue() -
3011
3012 This API returns the operating channel of the requested device mode
3013
3014 \param - pHddCtx - Pointer to the HDD context.
3015 - mode - Device mode for which operating channel is required
3016 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
3017 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
3018 \return - channel number. "0" id the requested device is not found OR it is not connected.
3019 --------------------------------------------------------------------------*/
3020v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
3021{
3022 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3023 VOS_STATUS status;
3024 hdd_adapter_t *pAdapter;
3025 v_U8_t operatingChannel = 0;
3026
3027 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3028
3029 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3030 {
3031 pAdapter = pAdapterNode->pAdapter;
3032
3033 if( mode == pAdapter->device_mode )
3034 {
3035 switch(pAdapter->device_mode)
3036 {
3037 case WLAN_HDD_INFRA_STATION:
3038 case WLAN_HDD_P2P_CLIENT:
3039 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3040 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
3041 break;
3042 case WLAN_HDD_SOFTAP:
3043 case WLAN_HDD_P2P_GO:
3044 /*softap connection info */
3045 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3046 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
3047 break;
3048 default:
3049 break;
3050 }
3051
3052 break; //Found the device of interest. break the loop
3053 }
3054
3055 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3056 pAdapterNode = pNext;
3057 }
3058 return operatingChannel;
3059}
3060
3061#ifdef WLAN_FEATURE_PACKET_FILTERING
3062/**---------------------------------------------------------------------------
3063
3064 \brief hdd_set_multicast_list() -
3065
3066 This used to set the multicast address list.
3067
3068 \param - dev - Pointer to the WLAN device.
3069 - skb - Pointer to OS packet (sk_buff).
3070 \return - success/fail
3071
3072 --------------------------------------------------------------------------*/
3073static void hdd_set_multicast_list(struct net_device *dev)
3074{
3075 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07003076 int mc_count;
3077 int i = 0;
3078 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303079
3080 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07003081 {
3082 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303083 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003084 return;
3085 }
3086
3087 if (dev->flags & IFF_ALLMULTI)
3088 {
3089 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003090 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303091 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003092 }
3093 else
3094 {
3095 mc_count = netdev_mc_count(dev);
3096 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003097 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07003098 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
3099 {
3100 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003101 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303102 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003103 return;
3104 }
3105
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303106 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07003107
3108 netdev_for_each_mc_addr(ha, dev) {
3109 if (i == mc_count)
3110 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303111 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
3112 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
3113 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003114 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303115 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07003116 i++;
3117 }
3118 }
3119 return;
3120}
3121#endif
3122
3123/**---------------------------------------------------------------------------
3124
3125 \brief hdd_select_queue() -
3126
3127 This function is registered with the Linux OS for network
3128 core to decide which queue to use first.
3129
3130 \param - dev - Pointer to the WLAN device.
3131 - skb - Pointer to OS packet (sk_buff).
3132 \return - ac, Queue Index/access category corresponding to UP in IP header
3133
3134 --------------------------------------------------------------------------*/
3135v_U16_t hdd_select_queue(struct net_device *dev,
3136 struct sk_buff *skb)
3137{
3138 return hdd_wmm_select_queue(dev, skb);
3139}
3140
3141
3142/**---------------------------------------------------------------------------
3143
3144 \brief hdd_wlan_initial_scan() -
3145
3146 This function triggers the initial scan
3147
3148 \param - pAdapter - Pointer to the HDD adapter.
3149
3150 --------------------------------------------------------------------------*/
3151void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
3152{
3153 tCsrScanRequest scanReq;
3154 tCsrChannelInfo channelInfo;
3155 eHalStatus halStatus;
3156 unsigned long scanId;
3157 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3158
3159 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
3160 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
3161 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
3162
3163 if(sme_Is11dSupported(pHddCtx->hHal))
3164 {
3165 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
3166 if ( HAL_STATUS_SUCCESS( halStatus ) )
3167 {
3168 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
3169 if( !scanReq.ChannelInfo.ChannelList )
3170 {
3171 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
3172 vos_mem_free(channelInfo.ChannelList);
3173 return;
3174 }
3175 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
3176 channelInfo.numOfChannels);
3177 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
3178 vos_mem_free(channelInfo.ChannelList);
3179 }
3180
3181 scanReq.scanType = eSIR_PASSIVE_SCAN;
3182 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
3183 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
3184 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
3185 }
3186 else
3187 {
3188 scanReq.scanType = eSIR_ACTIVE_SCAN;
3189 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
3190 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
3191 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
3192 }
3193
3194 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
3195 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3196 {
3197 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
3198 __func__, halStatus );
3199 }
3200
3201 if(sme_Is11dSupported(pHddCtx->hHal))
3202 vos_mem_free(scanReq.ChannelInfo.ChannelList);
3203}
3204
3205struct fullPowerContext
3206{
3207 struct completion completion;
3208 unsigned int magic;
3209};
3210#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
3211
3212/**---------------------------------------------------------------------------
3213
3214 \brief hdd_full_power_callback() - HDD full power callback function
3215
3216 This is the function invoked by SME to inform the result of a full power
3217 request issued by HDD
3218
3219 \param - callbackcontext - Pointer to cookie
3220 \param - status - result of request
3221
3222 \return - None
3223
3224 --------------------------------------------------------------------------*/
3225static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
3226{
3227 struct fullPowerContext *pContext = callbackContext;
3228
3229 hddLog(VOS_TRACE_LEVEL_INFO,
3230 "%s: context = %p, status = %d", pContext, status);
3231
3232 if (NULL == callbackContext)
3233 {
3234 hddLog(VOS_TRACE_LEVEL_ERROR,
3235 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003236 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07003237 return;
3238 }
3239
3240 /* there is a race condition that exists between this callback function
3241 and the caller since the caller could time out either before or
3242 while this code is executing. we'll assume the timeout hasn't
3243 occurred, but we'll verify that right before we save our work */
3244
3245 if (POWER_CONTEXT_MAGIC != pContext->magic)
3246 {
3247 /* the caller presumably timed out so there is nothing we can do */
3248 hddLog(VOS_TRACE_LEVEL_WARN,
3249 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003250 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07003251 return;
3252 }
3253
3254 /* the race is on. caller could have timed out immediately after
3255 we verified the magic, but if so, caller will wait a short time
3256 for us to notify the caller, so the context will stay valid */
3257 complete(&pContext->completion);
3258}
3259
3260/**---------------------------------------------------------------------------
3261
3262 \brief hdd_wlan_exit() - HDD WLAN exit function
3263
3264 This is the driver exit point (invoked during rmmod)
3265
3266 \param - pHddCtx - Pointer to the HDD Context
3267
3268 \return - None
3269
3270 --------------------------------------------------------------------------*/
3271void hdd_wlan_exit(hdd_context_t *pHddCtx)
3272{
3273 eHalStatus halStatus;
3274 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
3275 VOS_STATUS vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07003276#ifdef CONFIG_CFG80211
3277 struct wiphy *wiphy = pHddCtx->wiphy;
3278#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003279 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003280 struct fullPowerContext powerContext;
3281 long lrc;
3282
3283 ENTER();
3284
Jeff Johnson88ba7742013-02-27 14:36:02 -08003285 if (VOS_FTM_MODE != hdd_get_conparam())
3286 {
3287 // Unloading, restart logic is no more required.
3288 wlan_hdd_restart_deinit(pHddCtx);
3289 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003290
Jeff Johnson295189b2012-06-20 16:38:30 -07003291#ifdef CONFIG_CFG80211
Jeff Johnson295189b2012-06-20 16:38:30 -07003292 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003293 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003294 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003295 {
3296 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
3297 WLAN_HDD_INFRA_STATION);
3298 if (pAdapter == NULL)
3299 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3300
3301 if (pAdapter != NULL)
3302 {
3303 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
3304 hdd_UnregisterWext(pAdapter->dev);
3305 }
3306 }
3307 }
3308#endif
3309
Jeff Johnson295189b2012-06-20 16:38:30 -07003310 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08003311 {
3312 wlan_hdd_ftm_close(pHddCtx);
3313 goto free_hdd_ctx;
3314 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003315 //Stop the Interface TX queue.
3316 //netif_tx_disable(pWlanDev);
3317 //netif_carrier_off(pWlanDev);
3318
Jeff Johnson295189b2012-06-20 16:38:30 -07003319 if (VOS_STA_SAP_MODE == hdd_get_conparam())
3320 {
3321 pAdapter = hdd_get_adapter(pHddCtx,
3322 WLAN_HDD_SOFTAP);
3323 }
3324 else
3325 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003326 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003327 {
3328 pAdapter = hdd_get_adapter(pHddCtx,
3329 WLAN_HDD_INFRA_STATION);
3330 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003331 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003332 /* DeRegister with platform driver as client for Suspend/Resume */
3333 vosStatus = hddDeregisterPmOps(pHddCtx);
3334 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3335 {
3336 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
3337 VOS_ASSERT(0);
3338 }
3339
3340 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
3341 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3342 {
3343 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
3344 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003345
Chilam NG571c65a2013-01-19 12:27:36 +05303346#ifdef FEATURE_WLAN_TDLS
3347 wlan_hdd_tdls_exit();
3348#endif
3349
Jeff Johnson295189b2012-06-20 16:38:30 -07003350 // Cancel any outstanding scan requests. We are about to close all
3351 // of our adapters, but an adapter structure is what SME passes back
3352 // to our callback function. Hence if there are any outstanding scan
3353 // requests then there is a race condition between when the adapter
3354 // is closed and when the callback is invoked. We try to resolve that
3355 // race condition here by canceling any outstanding scans before we
3356 // close the adapters.
3357 // Note that the scans may be cancelled in an asynchronous manner, so
3358 // ideally there needs to be some kind of synchronization. Rather than
3359 // introduce a new synchronization here, we will utilize the fact that
3360 // we are about to Request Full Power, and since that is synchronized,
3361 // the expectation is that by the time Request Full Power has completed,
3362 // all scans will be cancelled.
3363 hdd_abort_mac_scan( pHddCtx );
3364
3365 //Disable IMPS/BMPS as we do not want the device to enter any power
3366 //save mode during shutdown
3367 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3368 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3369 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
3370
3371 //Ensure that device is in full power as we will touch H/W during vos_Stop
3372 init_completion(&powerContext.completion);
3373 powerContext.magic = POWER_CONTEXT_MAGIC;
3374
3375 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
3376 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
3377
3378 if (eHAL_STATUS_SUCCESS != halStatus)
3379 {
3380 if (eHAL_STATUS_PMC_PENDING == halStatus)
3381 {
3382 /* request was sent -- wait for the response */
3383 lrc = wait_for_completion_interruptible_timeout(
3384 &powerContext.completion,
3385 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
3386 /* either we have a response or we timed out
3387 either way, first invalidate our magic */
3388 powerContext.magic = 0;
3389 if (lrc <= 0)
3390 {
3391 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003392 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07003393 /* there is a race condition such that the callback
3394 function could be executing at the same time we are. of
3395 primary concern is if the callback function had already
3396 verified the "magic" but hasn't yet set the completion
3397 variable. Since the completion variable is on our
3398 stack, we'll delay just a bit to make sure the data is
3399 still valid if that is the case */
3400 msleep(50);
3401 }
3402 }
3403 else
3404 {
3405 hddLog(VOS_TRACE_LEVEL_ERROR,
3406 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003407 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07003408 VOS_ASSERT(0);
3409 /* continue -- need to clean up as much as possible */
3410 }
3411 }
3412
3413 // Unregister the Net Device Notifier
3414 unregister_netdevice_notifier(&hdd_netdev_notifier);
3415
Jeff Johnson295189b2012-06-20 16:38:30 -07003416 hdd_stop_all_adapters( pHddCtx );
3417
Jeff Johnson295189b2012-06-20 16:38:30 -07003418#ifdef WLAN_BTAMP_FEATURE
3419 vosStatus = WLANBAP_Stop(pVosContext);
3420 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3421 {
3422 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3423 "%s: Failed to stop BAP",__func__);
3424 }
3425#endif //WLAN_BTAMP_FEATURE
3426
3427 //Stop all the modules
3428 vosStatus = vos_stop( pVosContext );
3429 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3430 {
3431 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3432 "%s: Failed to stop VOSS",__func__);
3433 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3434 }
3435
Jeff Johnson295189b2012-06-20 16:38:30 -07003436 //Assert Deep sleep signal now to put Libra HW in lowest power state
3437 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
3438 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3439
3440 //Vote off any PMIC voltage supplies
3441 vos_chipPowerDown(NULL, NULL, NULL);
3442
3443 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
3444
3445 //Clean up HDD Nlink Service
3446 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
3447 nl_srv_exit();
3448
3449 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07003450 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003451
3452 //Close the scheduler before calling vos_close to make sure no thread is
3453 // scheduled after the each module close is called i.e after all the data
3454 // structures are freed.
3455 vosStatus = vos_sched_close( pVosContext );
3456 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
3457 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
3458 "%s: Failed to close VOSS Scheduler",__func__);
3459 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3460 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003461#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07003462#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3463 /* Destroy the wake lock */
3464 wake_lock_destroy(&pHddCtx->rx_wake_lock);
3465#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08003466 /* Destroy the wake lock */
3467 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003468#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003469
3470 //Close VOSS
3471 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
3472 vos_close(pVosContext);
3473
Jeff Johnson295189b2012-06-20 16:38:30 -07003474 //Close Watchdog
3475 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3476 vos_watchdog_close(pVosContext);
3477
3478 /* Cancel the vote for XO Core ON.
3479 * This is done here to ensure there is no race condition since MC, TX and WD threads have
3480 * exited at this point
3481 */
3482 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
3483 " when WLAN is turned OFF\n");
3484 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
3485 {
3486 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
3487 " Not returning failure."
3488 " Power consumed will be high\n");
3489 }
3490
3491 hdd_close_all_adapters( pHddCtx );
3492
3493
3494 //Free up dynamically allocated members inside HDD Adapter
3495 kfree(pHddCtx->cfg_ini);
3496 pHddCtx->cfg_ini= NULL;
3497
3498 /* free the power on lock from platform driver */
3499 if (free_riva_power_on_lock("wlan"))
3500 {
3501 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
3502 __func__);
3503 }
3504
Jeff Johnson88ba7742013-02-27 14:36:02 -08003505free_hdd_ctx:
Jeff Johnson295189b2012-06-20 16:38:30 -07003506#ifdef CONFIG_CFG80211
Jeff Johnson88ba7742013-02-27 14:36:02 -08003507 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07003508 wiphy_free(wiphy) ;
3509#else
3510 vos_mem_free( pHddCtx );
3511#endif
3512 if (hdd_is_ssr_required())
3513 {
3514 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07003515 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07003516 msleep(5000);
3517 }
3518 hdd_set_ssr_required (VOS_FALSE);
3519}
3520
3521
3522/**---------------------------------------------------------------------------
3523
3524 \brief hdd_update_config_from_nv() - Function to update the contents of
3525 the running configuration with parameters taken from NV storage
3526
3527 \param - pHddCtx - Pointer to the HDD global context
3528
3529 \return - VOS_STATUS_SUCCESS if successful
3530
3531 --------------------------------------------------------------------------*/
3532static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
3533{
Jeff Johnson295189b2012-06-20 16:38:30 -07003534 v_BOOL_t itemIsValid = VOS_FALSE;
3535 VOS_STATUS status;
3536 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
3537 v_U8_t macLoop;
3538
3539 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
3540 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
3541 if(status != VOS_STATUS_SUCCESS)
3542 {
3543 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
3544 return VOS_STATUS_E_FAILURE;
3545 }
3546
3547 if (itemIsValid == VOS_TRUE)
3548 {
3549 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
3550 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
3551 VOS_MAX_CONCURRENCY_PERSONA);
3552 if(status != VOS_STATUS_SUCCESS)
3553 {
3554 /* Get MAC from NV fail, not update CFG info
3555 * INI MAC value will be used for MAC setting */
3556 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
3557 return VOS_STATUS_E_FAILURE;
3558 }
3559
3560 /* If first MAC is not valid, treat all others are not valid
3561 * Then all MACs will be got from ini file */
3562 if(vos_is_macaddr_zero(&macFromNV[0]))
3563 {
3564 /* MAC address in NV file is not configured yet */
3565 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
3566 return VOS_STATUS_E_INVAL;
3567 }
3568
3569 /* Get MAC address from NV, update CFG info */
3570 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
3571 {
3572 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
3573 {
3574 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
3575 /* This MAC is not valid, skip it
3576 * This MAC will be got from ini file */
3577 }
3578 else
3579 {
3580 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
3581 (v_U8_t *)&macFromNV[macLoop].bytes[0],
3582 VOS_MAC_ADDR_SIZE);
3583 }
3584 }
3585 }
3586 else
3587 {
3588 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
3589 return VOS_STATUS_E_FAILURE;
3590 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003591
Jeff Johnson295189b2012-06-20 16:38:30 -07003592
3593 return VOS_STATUS_SUCCESS;
3594}
3595
3596/**---------------------------------------------------------------------------
3597
3598 \brief hdd_post_voss_start_config() - HDD post voss start config helper
3599
3600 \param - pAdapter - Pointer to the HDD
3601
3602 \return - None
3603
3604 --------------------------------------------------------------------------*/
3605VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
3606{
3607 eHalStatus halStatus;
3608 v_U32_t listenInterval;
3609
Jeff Johnson295189b2012-06-20 16:38:30 -07003610
3611 // Send ready indication to the HDD. This will kick off the MAC
3612 // into a 'running' state and should kick off an initial scan.
3613 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
3614 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3615 {
3616 hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
3617 "code %08d [x%08x]",__func__, halStatus, halStatus );
3618 return VOS_STATUS_E_FAILURE;
3619 }
3620
3621 // Set default LI into HDD context,
3622 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
3623 // And RIVA will crash
3624 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
3625 pHddCtx->hdd_actual_LI_value = listenInterval;
3626
3627 return VOS_STATUS_SUCCESS;
3628}
3629
Jeff Johnson295189b2012-06-20 16:38:30 -07003630/* wake lock APIs for HDD */
3631void hdd_prevent_suspend(void)
3632{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003633#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003634 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003635#else
3636 wcnss_prevent_suspend();
3637#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003638}
3639
3640void hdd_allow_suspend(void)
3641{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003642#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003643 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003644#else
3645 wcnss_allow_suspend();
3646#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003647}
3648
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003649void hdd_allow_suspend_timeout(v_U32_t timeout)
3650{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003651#ifdef WLAN_OPEN_SOURCE
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003652 wake_lock_timeout(&wlan_wake_lock, timeout);
3653#else
3654 /* Do nothing as there is no API in wcnss for timeout*/
3655#endif
3656}
3657
Jeff Johnson295189b2012-06-20 16:38:30 -07003658/**---------------------------------------------------------------------------
3659
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003660 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
3661 information between Host and Riva
3662
3663 This function gets reported version of FW
3664 It also finds the version of Riva headers used to compile the host
3665 It compares the above two and prints a warning if they are different
3666 It gets the SW and HW version string
3667 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
3668 indicating the features they support through a bitmap
3669
3670 \param - pHddCtx - Pointer to HDD context
3671
3672 \return - void
3673
3674 --------------------------------------------------------------------------*/
3675
3676void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
3677{
3678
3679 tSirVersionType versionCompiled;
3680 tSirVersionType versionReported;
3681 tSirVersionString versionString;
3682 tANI_U8 fwFeatCapsMsgSupported = 0;
3683 VOS_STATUS vstatus;
3684
3685 /* retrieve and display WCNSS version information */
3686 do {
3687
3688 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
3689 &versionCompiled);
3690 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3691 {
3692 hddLog(VOS_TRACE_LEVEL_FATAL,
3693 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003694 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003695 break;
3696 }
3697
3698 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
3699 &versionReported);
3700 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3701 {
3702 hddLog(VOS_TRACE_LEVEL_FATAL,
3703 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003704 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003705 break;
3706 }
3707
3708 if ((versionCompiled.major != versionReported.major) ||
3709 (versionCompiled.minor != versionReported.minor) ||
3710 (versionCompiled.version != versionReported.version) ||
3711 (versionCompiled.revision != versionReported.revision))
3712 {
3713 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
3714 "Host expected %u.%u.%u.%u\n",
3715 WLAN_MODULE_NAME,
3716 (int)versionReported.major,
3717 (int)versionReported.minor,
3718 (int)versionReported.version,
3719 (int)versionReported.revision,
3720 (int)versionCompiled.major,
3721 (int)versionCompiled.minor,
3722 (int)versionCompiled.version,
3723 (int)versionCompiled.revision);
3724 }
3725 else
3726 {
3727 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
3728 WLAN_MODULE_NAME,
3729 (int)versionReported.major,
3730 (int)versionReported.minor,
3731 (int)versionReported.version,
3732 (int)versionReported.revision);
3733 }
3734
3735 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
3736 versionString,
3737 sizeof(versionString));
3738 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3739 {
3740 hddLog(VOS_TRACE_LEVEL_FATAL,
3741 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003742 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003743 break;
3744 }
3745
3746 pr_info("%s: WCNSS software version %s\n",
3747 WLAN_MODULE_NAME, versionString);
3748
3749 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
3750 versionString,
3751 sizeof(versionString));
3752 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3753 {
3754 hddLog(VOS_TRACE_LEVEL_FATAL,
3755 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003756 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003757 break;
3758 }
3759
3760 pr_info("%s: WCNSS hardware version %s\n",
3761 WLAN_MODULE_NAME, versionString);
3762
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003763 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
3764 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003765 send the message only if it the riva is 1.1
3766 minor numbers for different riva branches:
3767 0 -> (1.0)Mainline Build
3768 1 -> (1.1)Mainline Build
3769 2->(1.04) Stability Build
3770 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003771 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003772 ((versionReported.minor>=1) && (versionReported.version>=1)))
3773 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
3774 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003775
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003776 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08003777 {
3778#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
3779 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
3780 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
3781#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003782 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08003783 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003784
3785 } while (0);
3786
3787}
3788
3789/**---------------------------------------------------------------------------
3790
Jeff Johnson295189b2012-06-20 16:38:30 -07003791 \brief hdd_wlan_startup() - HDD init function
3792
3793 This is the driver startup code executed once a WLAN device has been detected
3794
3795 \param - dev - Pointer to the underlying device
3796
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003797 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07003798
3799 --------------------------------------------------------------------------*/
3800
3801int hdd_wlan_startup(struct device *dev )
3802{
3803 VOS_STATUS status;
3804 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003805 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003806 hdd_context_t *pHddCtx = NULL;
3807 v_CONTEXT_t pVosContext= NULL;
3808#ifdef WLAN_BTAMP_FEATURE
3809 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
3810 WLANBAP_ConfigType btAmpConfig;
3811 hdd_config_t *pConfig;
3812#endif
3813 int ret;
3814#ifdef CONFIG_CFG80211
3815 struct wiphy *wiphy;
3816#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003817
3818 ENTER();
3819#ifdef CONFIG_CFG80211
3820 /*
3821 * cfg80211: wiphy allocation
3822 */
3823 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
3824
3825 if(wiphy == NULL)
3826 {
3827 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003828 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003829 }
3830
3831 pHddCtx = wiphy_priv(wiphy);
3832
3833#else
3834
3835 pHddCtx = vos_mem_malloc ( sizeof( hdd_context_t ) );
3836 if(pHddCtx == NULL)
3837 {
3838 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003839 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07003840 }
3841
3842#endif
3843 //Initialize the adapter context to zeros.
3844 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
3845
3846#ifdef CONFIG_CFG80211
3847 pHddCtx->wiphy = wiphy;
3848#endif
3849 hdd_prevent_suspend();
3850 pHddCtx->isLoadUnloadInProgress = TRUE;
3851
3852 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
3853
3854 /*Get vos context here bcoz vos_open requires it*/
3855 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
3856
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08003857 if(pVosContext == NULL)
3858 {
3859 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
3860 goto err_free_hdd_context;
3861 }
3862
Jeff Johnson295189b2012-06-20 16:38:30 -07003863 //Save the Global VOSS context in adapter context for future.
3864 pHddCtx->pvosContext = pVosContext;
3865
3866 //Save the adapter context in global context for future.
3867 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
3868
Jeff Johnson295189b2012-06-20 16:38:30 -07003869 pHddCtx->parent_dev = dev;
3870
3871 init_completion(&pHddCtx->full_pwr_comp_var);
3872 init_completion(&pHddCtx->standby_comp_var);
3873 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003874 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003875 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003876
3877 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
3878
3879 // Load all config first as TL config is needed during vos_open
3880 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
3881 if(pHddCtx->cfg_ini == NULL)
3882 {
3883 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
3884 goto err_free_hdd_context;
3885 }
3886
3887 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
3888
3889 // Read and parse the qcom_cfg.ini file
3890 status = hdd_parse_config_ini( pHddCtx );
3891 if ( VOS_STATUS_SUCCESS != status )
3892 {
3893 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
3894 __func__, WLAN_INI_FILE);
3895 goto err_config;
3896 }
3897
3898#ifdef CONFIG_CFG80211
3899 /*
3900 * cfg80211: Initialization and registration ...
3901 */
3902 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
3903 {
3904 hddLog(VOS_TRACE_LEVEL_FATAL,
3905 "%s: wlan_hdd_cfg80211_register return failure", __func__);
3906 goto err_wiphy_reg;
3907 }
3908#endif
3909
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003910 // Update VOS trace levels based upon the cfg.ini
3911 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
3912 pHddCtx->cfg_ini->vosTraceEnableBAP);
3913 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
3914 pHddCtx->cfg_ini->vosTraceEnableTL);
3915 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
3916 pHddCtx->cfg_ini->vosTraceEnableWDI);
3917 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
3918 pHddCtx->cfg_ini->vosTraceEnableHDD);
3919 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
3920 pHddCtx->cfg_ini->vosTraceEnableSME);
3921 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
3922 pHddCtx->cfg_ini->vosTraceEnablePE);
3923 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
3924 pHddCtx->cfg_ini->vosTraceEnableWDA);
3925 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
3926 pHddCtx->cfg_ini->vosTraceEnableSYS);
3927 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
3928 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003929 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
3930 pHddCtx->cfg_ini->vosTraceEnableSAP);
3931 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
3932 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003933
Jeff Johnson295189b2012-06-20 16:38:30 -07003934 // Update WDI trace levels based upon the cfg.ini
3935 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
3936 pHddCtx->cfg_ini->wdiTraceEnableDAL);
3937 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
3938 pHddCtx->cfg_ini->wdiTraceEnableCTL);
3939 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
3940 pHddCtx->cfg_ini->wdiTraceEnableDAT);
3941 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
3942 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003943
Jeff Johnson88ba7742013-02-27 14:36:02 -08003944 if (VOS_FTM_MODE == hdd_get_conparam())
3945 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003946 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
3947 {
3948 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
3949 goto err_free_hdd_context;
3950 }
3951 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
3952 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08003953 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003954
Jeff Johnson88ba7742013-02-27 14:36:02 -08003955 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07003956 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3957 {
3958 status = vos_watchdog_open(pVosContext,
3959 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
3960
3961 if(!VOS_IS_STATUS_SUCCESS( status ))
3962 {
3963 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
3964#ifdef CONFIG_CFG80211
3965 goto err_wiphy_reg;
3966#else
3967 goto err_config;
3968#endif
3969 }
3970 }
3971
3972 pHddCtx->isLogpInProgress = FALSE;
3973 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
3974
Jeff Johnson295189b2012-06-20 16:38:30 -07003975 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
3976 if(!VOS_IS_STATUS_SUCCESS(status))
3977 {
3978 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003979 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07003980 }
3981
Jeff Johnson295189b2012-06-20 16:38:30 -07003982 status = vos_open( &pVosContext, 0);
3983 if ( !VOS_IS_STATUS_SUCCESS( status ))
3984 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003985 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
3986 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07003987 }
3988
Jeff Johnson295189b2012-06-20 16:38:30 -07003989 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
3990
3991 if ( NULL == pHddCtx->hHal )
3992 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003993 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003994 goto err_vosclose;
3995 }
3996
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003997 status = vos_preStart( pHddCtx->pvosContext );
3998 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3999 {
4000 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
4001 goto err_vosclose;
4002 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004003
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004004 /* Note that the vos_preStart() sequence triggers the cfg download.
4005 The cfg download must occur before we update the SME config
4006 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07004007 status = hdd_set_sme_config( pHddCtx );
4008
4009 if ( VOS_STATUS_SUCCESS != status )
4010 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004011 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
4012 goto err_vosclose;
4013 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004014
4015 //Initialize the WMM module
4016 status = hdd_wmm_init(pHddCtx);
4017 if (!VOS_IS_STATUS_SUCCESS(status))
4018 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004019 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004020 goto err_vosclose;
4021 }
4022
Jeff Johnson295189b2012-06-20 16:38:30 -07004023 /* In the integrated architecture we update the configuration from
4024 the INI file and from NV before vOSS has been started so that
4025 the final contents are available to send down to the cCPU */
4026
4027 // Apply the cfg.ini to cfg.dat
4028 if (FALSE == hdd_update_config_dat(pHddCtx))
4029 {
4030 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
4031 goto err_vosclose;
4032 }
4033
4034 // Apply the NV to cfg.dat
4035 /* Prima Update MAC address only at here */
4036 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
4037 {
4038#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
4039 /* There was not a valid set of MAC Addresses in NV. See if the
4040 default addresses were modified by the cfg.ini settings. If so,
4041 we'll use them, but if not, we'll autogenerate a set of MAC
4042 addresses based upon the device serial number */
4043
4044 static const v_MACADDR_t default_address =
4045 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
4046 unsigned int serialno;
4047 int i;
4048
4049 serialno = wcnss_get_serial_number();
4050 if ((0 != serialno) &&
4051 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
4052 sizeof(default_address))))
4053 {
4054 /* cfg.ini has the default address, invoke autogen logic */
4055
4056 /* MAC address has 3 bytes of OUI so we have a maximum of 3
4057 bytes of the serial number that can be used to generate
4058 the other 3 bytes of the MAC address. Mask off all but
4059 the lower 3 bytes (this will also make sure we don't
4060 overflow in the next step) */
4061 serialno &= 0x00FFFFFF;
4062
4063 /* we need a unique address for each session */
4064 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
4065
4066 /* autogen all addresses */
4067 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4068 {
4069 /* start with the entire default address */
4070 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
4071 /* then replace the lower 3 bytes */
4072 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
4073 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
4074 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
4075
4076 serialno++;
4077 }
4078
4079 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
4080 MAC_ADDRESS_STR,
4081 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4082 }
4083 else
4084#endif //WLAN_AUTOGEN_MACADDR_FEATURE
4085 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004086 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004087 "%s: Invalid MAC address in NV, using MAC from ini file "
4088 MAC_ADDRESS_STR, __func__,
4089 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4090 }
4091 }
4092 {
4093 eHalStatus halStatus;
4094 // Set the MAC Address
4095 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
4096 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
4097 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
4098 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
4099
4100 if (!HAL_STATUS_SUCCESS( halStatus ))
4101 {
4102 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
4103 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08004104 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004105 }
4106 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004107
4108 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
4109 Note: Firmware image will be read and downloaded inside vos_start API */
4110 status = vos_start( pHddCtx->pvosContext );
4111 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4112 {
4113 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
4114 goto err_vosclose;
4115 }
4116
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004117 /* Exchange capability info between Host and FW and also get versioning info from FW */
4118 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004119
4120 status = hdd_post_voss_start_config( pHddCtx );
4121 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4122 {
4123 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
4124 __func__);
4125 goto err_vosstop;
4126 }
4127
Jeff Johnson295189b2012-06-20 16:38:30 -07004128 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4129 {
4130 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
4131 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4132 }
4133 else
4134 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004135 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
4136 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4137 if (pAdapter != NULL)
4138 {
4139#ifdef WLAN_FEATURE_P2P
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304140 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07004141 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304142 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
4143 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
4144 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07004145
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304146 /* Generate the P2P Device Address. This consists of the device's
4147 * primary MAC address with the locally administered bit set.
4148 */
4149 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07004150 }
4151 else
4152 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304153 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
4154 if (p2p_dev_addr != NULL)
4155 {
4156 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
4157 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
4158 }
4159 else
4160 {
4161 hddLog(VOS_TRACE_LEVEL_FATAL,
4162 "%s: Failed to allocate mac_address for p2p_device",
4163 __func__);
4164 goto err_close_adapter;
4165 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004166 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004167
4168 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
4169 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
4170 if ( NULL == pP2pAdapter )
4171 {
4172 hddLog(VOS_TRACE_LEVEL_FATAL,
4173 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004174 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004175 goto err_close_adapter;
4176 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004177#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004178 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004179 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004180
4181 if( pAdapter == NULL )
4182 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004183 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
4184 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004185 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004186
Jeff Johnson295189b2012-06-20 16:38:30 -07004187#ifdef WLAN_BTAMP_FEATURE
4188 vStatus = WLANBAP_Open(pVosContext);
4189 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4190 {
4191 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4192 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004193 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004194 }
4195
4196 vStatus = BSL_Init(pVosContext);
4197 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4198 {
4199 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4200 "%s: Failed to Init BSL",__func__);
4201 goto err_bap_close;
4202 }
4203 vStatus = WLANBAP_Start(pVosContext);
4204 if (!VOS_IS_STATUS_SUCCESS(vStatus))
4205 {
4206 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4207 "%s: Failed to start TL",__func__);
4208 goto err_bap_close;
4209 }
4210
4211 pConfig = pHddCtx->cfg_ini;
4212 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
4213 status = WLANBAP_SetConfig(&btAmpConfig);
4214
4215#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07004216
Jeff Johnson295189b2012-06-20 16:38:30 -07004217#ifdef FEATURE_WLAN_SCAN_PNO
4218 /*SME must send channel update configuration to RIVA*/
4219 sme_UpdateChannelConfig(pHddCtx->hHal);
4220#endif
4221
Jeff Johnson295189b2012-06-20 16:38:30 -07004222 /* Register with platform driver as client for Suspend/Resume */
4223 status = hddRegisterPmOps(pHddCtx);
4224 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4225 {
4226 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
4227#ifdef WLAN_BTAMP_FEATURE
4228 goto err_bap_stop;
4229#else
Jeff Johnsone7245742012-09-05 17:12:55 -07004230 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004231#endif //WLAN_BTAMP_FEATURE
4232 }
4233
4234 /* Register TM level change handler function to the platform */
4235 status = hddDevTmRegisterNotifyCallback(pHddCtx);
4236 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4237 {
4238 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
4239 goto err_unregister_pmops;
4240 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004241
4242 /* register for riva power on lock to platform driver */
4243 if (req_riva_power_on_lock("wlan"))
4244 {
4245 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
4246 __func__);
4247 goto err_unregister_pmops;
4248 }
4249
Jeff Johnson295189b2012-06-20 16:38:30 -07004250 // register net device notifier for device change notification
4251 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4252
4253 if(ret < 0)
4254 {
4255 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
4256 goto err_free_power_on_lock;
4257 }
4258
4259 //Initialize the nlink service
4260 if(nl_srv_init() != 0)
4261 {
4262 hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
4263 goto err_reg_netdev;
4264 }
4265
4266 //Initialize the BTC service
4267 if(btc_activate_service(pHddCtx) != 0)
4268 {
4269 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
4270 goto err_nl_srv;
4271 }
4272
4273#ifdef PTT_SOCK_SVC_ENABLE
4274 //Initialize the PTT service
4275 if(ptt_sock_activate_svc(pHddCtx) != 0)
4276 {
4277 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
4278 goto err_nl_srv;
4279 }
4280#endif
4281
Jeff Johnson295189b2012-06-20 16:38:30 -07004282 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004283#ifdef CONFIG_CFG80211
Jeff Johnson295189b2012-06-20 16:38:30 -07004284 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004285 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07004286 /* Action frame registered in one adapter which will
4287 * applicable to all interfaces
4288 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07004289 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07004290 }
4291#endif
4292
4293 mutex_init(&pHddCtx->sap_lock);
4294
4295 pHddCtx->isLoadUnloadInProgress = FALSE;
4296
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004297#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004298#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4299 /* Initialize the wake lcok */
4300 wake_lock_init(&pHddCtx->rx_wake_lock,
4301 WAKE_LOCK_SUSPEND,
4302 "qcom_rx_wakelock");
4303#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004304 /* Initialize the wake lcok */
4305 wake_lock_init(&pHddCtx->sap_wake_lock,
4306 WAKE_LOCK_SUSPEND,
4307 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004308#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004309
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004310 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
4311 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07004312
4313 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4314 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004315
4316 // Initialize the restart logic
4317 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05304318
4319#ifdef FEATURE_WLAN_TDLS
Hoonki Lee387663d2013-02-05 18:08:43 -08004320 if(0 != wlan_hdd_tdls_init(pAdapter->dev))
4321 {
4322 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_tdls_init failed",__func__);
4323 goto err_nl_srv;
4324 }
Chilam NG571c65a2013-01-19 12:27:36 +05304325#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004326
4327 goto success;
4328
4329err_nl_srv:
4330 nl_srv_exit();
4331
4332err_reg_netdev:
4333 unregister_netdevice_notifier(&hdd_netdev_notifier);
4334
4335err_free_power_on_lock:
4336 free_riva_power_on_lock("wlan");
4337
4338err_unregister_pmops:
4339 hddDevTmUnregisterNotifyCallback(pHddCtx);
4340 hddDeregisterPmOps(pHddCtx);
4341
4342#ifdef WLAN_BTAMP_FEATURE
4343err_bap_stop:
4344 WLANBAP_Stop(pVosContext);
4345#endif
4346
4347#ifdef WLAN_BTAMP_FEATURE
4348err_bap_close:
4349 WLANBAP_Close(pVosContext);
4350#endif
4351
Jeff Johnson295189b2012-06-20 16:38:30 -07004352err_close_adapter:
4353 hdd_close_all_adapters( pHddCtx );
4354
4355err_vosstop:
4356 vos_stop(pVosContext);
4357
4358err_vosclose:
4359 status = vos_sched_close( pVosContext );
4360 if (!VOS_IS_STATUS_SUCCESS(status)) {
4361 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4362 "%s: Failed to close VOSS Scheduler", __func__);
4363 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
4364 }
4365 vos_close(pVosContext );
4366
Jeff Johnson295189b2012-06-20 16:38:30 -07004367err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004368 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004369
4370err_wdclose:
4371 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4372 vos_watchdog_close(pVosContext);
4373
4374#ifdef CONFIG_CFG80211
4375err_wiphy_reg:
4376 wiphy_unregister(wiphy) ;
4377#endif
4378
4379err_config:
4380 kfree(pHddCtx->cfg_ini);
4381 pHddCtx->cfg_ini= NULL;
4382
4383err_free_hdd_context:
4384 hdd_allow_suspend();
4385#ifdef CONFIG_CFG80211
4386 wiphy_free(wiphy) ;
4387 //kfree(wdev) ;
4388#else
4389 vos_mem_free( pHddCtx );
4390#endif
4391 VOS_BUG(1);
4392
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08004393 if (hdd_is_ssr_required())
4394 {
4395 /* WDI timeout had happened during load, so SSR is needed here */
4396 subsystem_restart("wcnss");
4397 msleep(5000);
4398 }
4399 hdd_set_ssr_required (VOS_FALSE);
4400
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004401 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004402
4403success:
4404 EXIT();
4405 return 0;
4406}
4407
4408/**---------------------------------------------------------------------------
4409
Jeff Johnson32d95a32012-09-10 13:15:23 -07004410 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07004411
Jeff Johnson32d95a32012-09-10 13:15:23 -07004412 This is the driver entry point - called in different timeline depending
4413 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07004414
4415 \param - None
4416
4417 \return - 0 for success, non zero for failure
4418
4419 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07004420static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004421{
4422 VOS_STATUS status;
4423 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004424 struct device *dev = NULL;
4425 int ret_status = 0;
4426
4427 ENTER();
4428
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004429#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004430 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07004431#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004432
4433 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
4434 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
4435
4436 //Power Up Libra WLAN card first if not already powered up
4437 status = vos_chipPowerUp(NULL,NULL,NULL);
4438 if (!VOS_IS_STATUS_SUCCESS(status))
4439 {
4440 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
4441 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004442 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004443 }
4444
Jeff Johnson295189b2012-06-20 16:38:30 -07004445#ifdef ANI_BUS_TYPE_PCI
4446
4447 dev = wcnss_wlan_get_device();
4448
4449#endif // ANI_BUS_TYPE_PCI
4450
4451#ifdef ANI_BUS_TYPE_PLATFORM
4452 dev = wcnss_wlan_get_device();
4453#endif // ANI_BUS_TYPE_PLATFORM
4454
4455
4456 do {
4457 if (NULL == dev) {
4458 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
4459 ret_status = -1;
4460 break;
4461 }
4462
4463#ifdef MEMORY_DEBUG
4464 vos_mem_init();
4465#endif
4466
4467#ifdef TIMER_MANAGER
4468 vos_timer_manager_init();
4469#endif
4470
4471 /* Preopen VOSS so that it is ready to start at least SAL */
4472 status = vos_preOpen(&pVosContext);
4473
4474 if (!VOS_IS_STATUS_SUCCESS(status))
4475 {
4476 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
4477 ret_status = -1;
4478 break;
4479 }
4480
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004481#ifndef MODULE
4482 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
4483 */
4484 hdd_set_conparam((v_UINT_t)con_mode);
4485#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004486
4487 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004488 if (hdd_wlan_startup(dev))
4489 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004490 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004491 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004492 vos_preClose( &pVosContext );
4493 ret_status = -1;
4494 break;
4495 }
4496
4497 /* Cancel the vote for XO Core ON
4498 * This is done here for safety purposes in case we re-initialize without turning
4499 * it OFF in any error scenario.
4500 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004501 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07004502 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004503 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07004504 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4505 {
4506 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
4507 " Power consumed will be high\n");
4508 }
4509 } while (0);
4510
4511 if (0 != ret_status)
4512 {
4513 //Assert Deep sleep signal now to put Libra HW in lowest power state
4514 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4515 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
4516
4517 //Vote off any PMIC voltage supplies
4518 vos_chipPowerDown(NULL, NULL, NULL);
4519#ifdef TIMER_MANAGER
4520 vos_timer_exit();
4521#endif
4522#ifdef MEMORY_DEBUG
4523 vos_mem_exit();
4524#endif
4525
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004526#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004527 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004528#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004529 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
4530 }
4531 else
4532 {
4533 //Send WLAN UP indication to Nlink Service
4534 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
4535
4536 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
4537
4538 }
4539
4540 EXIT();
4541
4542 return ret_status;
4543}
4544
Jeff Johnson32d95a32012-09-10 13:15:23 -07004545/**---------------------------------------------------------------------------
4546
4547 \brief hdd_module_init() - Init Function
4548
4549 This is the driver entry point (invoked when module is loaded using insmod)
4550
4551 \param - None
4552
4553 \return - 0 for success, non zero for failure
4554
4555 --------------------------------------------------------------------------*/
4556#ifdef MODULE
4557static int __init hdd_module_init ( void)
4558{
4559 return hdd_driver_init();
4560}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004561#else /* #ifdef MODULE */
4562static int __init hdd_module_init ( void)
4563{
4564 /* Driver initialization is delayed to fwpath_changed_handler */
4565 return 0;
4566}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004567#endif /* #ifdef MODULE */
4568
Jeff Johnson295189b2012-06-20 16:38:30 -07004569
4570/**---------------------------------------------------------------------------
4571
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004572 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07004573
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004574 This is the driver exit point (invoked when module is unloaded using rmmod
4575 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07004576
4577 \param - None
4578
4579 \return - None
4580
4581 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004582static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004583{
4584 hdd_context_t *pHddCtx = NULL;
4585 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004586
4587 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
4588
4589 //Get the global vos context
4590 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4591
4592 if(!pVosContext)
4593 {
4594 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
4595 goto done;
4596 }
4597
4598 //Get the HDD context.
4599 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
4600
4601 if(!pHddCtx)
4602 {
4603 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
4604 }
4605 else
4606 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004607 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07004608 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07004609 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
4610 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07004611 }
4612
4613 pHddCtx->isLoadUnloadInProgress = TRUE;
4614 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4615
4616 //Do all the cleanup before deregistering the driver
4617 hdd_wlan_exit(pHddCtx);
4618 }
4619
Jeff Johnson295189b2012-06-20 16:38:30 -07004620 vos_preClose( &pVosContext );
4621
4622#ifdef TIMER_MANAGER
4623 vos_timer_exit();
4624#endif
4625#ifdef MEMORY_DEBUG
4626 vos_mem_exit();
4627#endif
4628
4629done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004630#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004631 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004632#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004633 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
4634}
4635
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004636/**---------------------------------------------------------------------------
4637
4638 \brief hdd_module_exit() - Exit function
4639
4640 This is the driver exit point (invoked when module is unloaded using rmmod)
4641
4642 \param - None
4643
4644 \return - None
4645
4646 --------------------------------------------------------------------------*/
4647static void __exit hdd_module_exit(void)
4648{
4649 hdd_driver_exit();
4650}
4651
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004652#ifdef MODULE
4653static int fwpath_changed_handler(const char *kmessage,
4654 struct kernel_param *kp)
4655{
4656 /* nothing to do when driver is DLKM */
4657 return 0;
4658}
4659
4660static int con_mode_handler(const char *kmessage,
4661 struct kernel_param *kp)
4662{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07004663 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004664}
4665#else /* #ifdef MODULE */
4666/**---------------------------------------------------------------------------
4667
4668 \brief fwpath_changed_handler() - Handler Function
4669
4670 This is the driver entry point
4671 - delayed driver initialization when driver is statically linked
4672 - invoked when module parameter fwpath is modified from userpspace to signal
4673 initializing the WLAN driver
4674
4675 \return - 0 for success, non zero for failure
4676
4677 --------------------------------------------------------------------------*/
4678static int fwpath_changed_handler(const char *kmessage,
4679 struct kernel_param *kp)
4680{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004681 int ret_status;
4682
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004683 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004684 ret_status = hdd_driver_init();
4685 wlan_hdd_inited = ret_status ? 0 : 1;
4686 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004687 }
4688
4689 hdd_driver_exit();
4690
4691 msleep(200);
4692
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004693 ret_status = hdd_driver_init();
4694 wlan_hdd_inited = ret_status ? 0 : 1;
4695 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004696}
4697
Jeff Johnson295189b2012-06-20 16:38:30 -07004698/**---------------------------------------------------------------------------
4699
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004700 \brief con_mode_handler() -
4701
4702 Handler function for module param con_mode when it is changed by userspace
4703 Dynamically linked - do nothing
4704 Statically linked - exit and init driver, as in rmmod and insmod
4705
4706 \param -
4707
4708 \return -
4709
4710 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004711static int con_mode_handler(const char *kmessage,
4712 struct kernel_param *kp)
4713{
4714 int ret = param_set_int(kmessage, kp);
4715
4716 if (ret)
4717 return ret;
4718
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004719 return fwpath_changed_handler(kmessage, kp);
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004720}
4721#endif /* #ifdef MODULE */
4722
4723/**---------------------------------------------------------------------------
4724
Jeff Johnson295189b2012-06-20 16:38:30 -07004725 \brief hdd_get_conparam() -
4726
4727 This is the driver exit point (invoked when module is unloaded using rmmod)
4728
4729 \param - None
4730
4731 \return - tVOS_CON_MODE
4732
4733 --------------------------------------------------------------------------*/
4734tVOS_CON_MODE hdd_get_conparam ( void )
4735{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004736#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07004737 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004738#else
4739 return (tVOS_CON_MODE)curr_con_mode;
4740#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004741}
4742void hdd_set_conparam ( v_UINT_t newParam )
4743{
4744 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004745#ifndef MODULE
4746 curr_con_mode = con_mode;
4747#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004748}
4749/**---------------------------------------------------------------------------
4750
4751 \brief hdd_softap_sta_deauth() - function
4752
4753 This to take counter measure to handle deauth req from HDD
4754
4755 \param - pAdapter - Pointer to the HDD
4756
4757 \param - enable - boolean value
4758
4759 \return - None
4760
4761 --------------------------------------------------------------------------*/
4762
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004763VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07004764{
Jeff Johnson295189b2012-06-20 16:38:30 -07004765 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004766 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07004767
4768 ENTER();
4769
4770 hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4771
4772 //Ignore request to deauth bcmc station
4773 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004774 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004775
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004776 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07004777
4778 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004779 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004780}
4781
4782/**---------------------------------------------------------------------------
4783
4784 \brief hdd_softap_sta_disassoc() - function
4785
4786 This to take counter measure to handle deauth req from HDD
4787
4788 \param - pAdapter - Pointer to the HDD
4789
4790 \param - enable - boolean value
4791
4792 \return - None
4793
4794 --------------------------------------------------------------------------*/
4795
4796void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
4797{
4798 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4799
4800 ENTER();
4801
4802 hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4803
4804 //Ignore request to disassoc bcmc station
4805 if( pDestMacAddress[0] & 0x1 )
4806 return;
4807
4808 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
4809}
4810
4811void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
4812{
4813 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4814
4815 ENTER();
4816
4817 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4818
4819 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
4820}
4821
Jeff Johnson295189b2012-06-20 16:38:30 -07004822/**---------------------------------------------------------------------------
4823 *
4824 * \brief hdd_get__concurrency_mode() -
4825 *
4826 *
4827 * \param - None
4828 *
4829 * \return - CONCURRENCY MODE
4830 *
4831 * --------------------------------------------------------------------------*/
4832tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
4833{
4834 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
4835 hdd_context_t *pHddCtx;
4836
4837 if (NULL != pVosContext)
4838 {
4839 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
4840 if (NULL != pHddCtx)
4841 {
4842 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
4843 }
4844 }
4845
4846 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004847 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004848 return VOS_STA;
4849}
4850
4851/* Decide whether to allow/not the apps power collapse.
4852 * Allow apps power collapse if we are in connected state.
4853 * if not, allow only if we are in IMPS */
4854v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
4855{
4856 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08004857 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07004858 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4859 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4860 hdd_adapter_t *pAdapter = NULL;
4861 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08004862 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004863
Jeff Johnson295189b2012-06-20 16:38:30 -07004864 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4865 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004866
Yathish9f22e662012-12-10 14:21:35 -08004867 concurrent_state = hdd_get_concurrency_mode();
4868
4869#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4870 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
4871 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
4872 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
4873 return TRUE;
4874#endif
4875
Jeff Johnson295189b2012-06-20 16:38:30 -07004876 /*loop through all adapters. TBD fix for Concurrency */
4877 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4878 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4879 {
4880 pAdapter = pAdapterNode->pAdapter;
4881 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4882 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4883 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08004884 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07004885 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08004886 && pmcState != STOPPED && pmcState != STANDBY)) ||
4887 (eANI_BOOLEAN_TRUE == scanRspPending))
Jeff Johnson295189b2012-06-20 16:38:30 -07004888 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08004889 hddLog( LOGE, "%s: do not allow APPS power collapse-"
4890 "pmcState = %d scanRspPending = %d",
4891 __func__, pmcState, scanRspPending );
Jeff Johnson295189b2012-06-20 16:38:30 -07004892 return FALSE;
4893 }
4894 }
4895 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4896 pAdapterNode = pNext;
4897 }
4898 return TRUE;
4899}
4900
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08004901/* Decides whether to send suspend notification to Riva
4902 * if any adapter is in BMPS; then it is required */
4903v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
4904{
4905 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
4906 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4907
4908 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
4909 {
4910 return TRUE;
4911 }
4912 return FALSE;
4913}
4914
Jeff Johnson295189b2012-06-20 16:38:30 -07004915void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
4916{
4917 switch(mode)
4918 {
4919 case WLAN_HDD_INFRA_STATION:
4920#ifdef WLAN_FEATURE_P2P
4921 case WLAN_HDD_P2P_CLIENT:
4922 case WLAN_HDD_P2P_GO:
4923#endif
4924 case WLAN_HDD_SOFTAP:
Jeff Johnsone7245742012-09-05 17:12:55 -07004925 pHddCtx->concurrency_mode |= (1 << mode);
4926 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07004927 break;
4928 default:
4929 break;
4930
4931 }
4932 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
4933 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
4934}
4935
4936
4937void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
4938{
4939 switch(mode)
4940 {
4941 case WLAN_HDD_INFRA_STATION:
4942#ifdef WLAN_FEATURE_P2P
4943 case WLAN_HDD_P2P_CLIENT:
4944 case WLAN_HDD_P2P_GO:
4945#endif
4946 case WLAN_HDD_SOFTAP:
4947 pHddCtx->no_of_sessions[mode]--;
4948 if (!(pHddCtx->no_of_sessions[mode]))
4949 pHddCtx->concurrency_mode &= (~(1 << mode));
4950 break;
4951 default:
4952 break;
4953 }
4954 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
4955 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
4956}
4957
Jeff Johnsone7245742012-09-05 17:12:55 -07004958/**---------------------------------------------------------------------------
4959 *
4960 * \brief wlan_hdd_restart_init
4961 *
4962 * This function initalizes restart timer/flag. An internal function.
4963 *
4964 * \param - pHddCtx
4965 *
4966 * \return - None
4967 *
4968 * --------------------------------------------------------------------------*/
4969
4970static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
4971{
4972 /* Initialize */
4973 pHddCtx->hdd_restart_retries = 0;
4974 atomic_set(&pHddCtx->isRestartInProgress, 0);
4975 vos_timer_init(&pHddCtx->hdd_restart_timer,
4976 VOS_TIMER_TYPE_SW,
4977 wlan_hdd_restart_timer_cb,
4978 pHddCtx);
4979}
4980/**---------------------------------------------------------------------------
4981 *
4982 * \brief wlan_hdd_restart_deinit
4983 *
4984 * This function cleans up the resources used. An internal function.
4985 *
4986 * \param - pHddCtx
4987 *
4988 * \return - None
4989 *
4990 * --------------------------------------------------------------------------*/
4991
4992static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
4993{
4994
4995 VOS_STATUS vos_status;
4996 /* Block any further calls */
4997 atomic_set(&pHddCtx->isRestartInProgress, 1);
4998 /* Cleanup */
4999 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
5000 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005001 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005002 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
5003 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005004 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005005
5006}
5007
5008/**---------------------------------------------------------------------------
5009 *
5010 * \brief wlan_hdd_framework_restart
5011 *
5012 * This function uses a cfg80211 API to start a framework initiated WLAN
5013 * driver module unload/load.
5014 *
5015 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
5016 *
5017 *
5018 * \param - pHddCtx
5019 *
5020 * \return - VOS_STATUS_SUCCESS: Success
5021 * VOS_STATUS_E_EMPTY: Adapter is Empty
5022 * VOS_STATUS_E_NOMEM: No memory
5023
5024 * --------------------------------------------------------------------------*/
5025
5026static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
5027{
5028 VOS_STATUS status = VOS_STATUS_SUCCESS;
5029 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5030 int len = (sizeof (struct ieee80211_mgmt));
5031 struct ieee80211_mgmt *mgmt = NULL;
5032
5033 /* Prepare the DEAUTH managment frame with reason code */
5034 mgmt = kzalloc(len, GFP_KERNEL);
5035 if(mgmt == NULL)
5036 {
5037 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1250df42012-12-10 14:31:52 -08005038 "%s: memory allocation failed (%d bytes)", __func__, len);
Jeff Johnsone7245742012-09-05 17:12:55 -07005039 return VOS_STATUS_E_NOMEM;
5040 }
5041 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
5042
5043 /* Iterate over all adapters/devices */
5044 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5045 do
5046 {
5047 if( (status == VOS_STATUS_SUCCESS) &&
5048 pAdapterNode &&
5049 pAdapterNode->pAdapter)
5050 {
5051 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5052 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
5053 pAdapterNode->pAdapter->dev->name,
5054 pAdapterNode->pAdapter->device_mode,
5055 pHddCtx->hdd_restart_retries + 1);
5056 /*
5057 * CFG80211 event to restart the driver
5058 *
5059 * 'cfg80211_send_unprot_deauth' sends a
5060 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
5061 * of SME(Linux Kernel) state machine.
5062 *
5063 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
5064 * the driver.
5065 *
5066 */
5067
5068 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
5069 }
5070 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5071 pAdapterNode = pNext;
5072 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
5073
5074
5075 /* Free the allocated management frame */
5076 kfree(mgmt);
5077
5078 /* Retry until we unload or reach max count */
5079 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
5080 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
5081
5082 return status;
5083
5084}
5085/**---------------------------------------------------------------------------
5086 *
5087 * \brief wlan_hdd_restart_timer_cb
5088 *
5089 * Restart timer callback. An internal function.
5090 *
5091 * \param - User data:
5092 *
5093 * \return - None
5094 *
5095 * --------------------------------------------------------------------------*/
5096
5097void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
5098{
5099 hdd_context_t *pHddCtx = usrDataForCallback;
5100 wlan_hdd_framework_restart(pHddCtx);
5101 return;
5102
5103}
5104
5105
5106/**---------------------------------------------------------------------------
5107 *
5108 * \brief wlan_hdd_restart_driver
5109 *
5110 * This function sends an event to supplicant to restart the WLAN driver.
5111 *
5112 * This function is called from vos_wlanRestart.
5113 *
5114 * \param - pHddCtx
5115 *
5116 * \return - VOS_STATUS_SUCCESS: Success
5117 * VOS_STATUS_E_EMPTY: Adapter is Empty
5118 * VOS_STATUS_E_ALREADY: Request already in progress
5119
5120 * --------------------------------------------------------------------------*/
5121VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
5122{
5123 VOS_STATUS status = VOS_STATUS_SUCCESS;
5124
5125 /* A tight check to make sure reentrancy */
5126 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
5127 {
5128 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
5129 "%s: WLAN restart is already in progress", __func__);
5130
5131 return VOS_STATUS_E_ALREADY;
5132 }
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005133 /* when WLAN driver is statically linked, then invoke SSR by sending
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005134 * the reset interrupt. If it is DLKM, then use restart API
5135 */
5136#ifdef MODULE
Jeff Johnsone7245742012-09-05 17:12:55 -07005137 status = wlan_hdd_framework_restart(pHddCtx);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005138#else
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005139#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005140 wcnss_reset_intr();
5141#endif
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005142#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005143
Jeff Johnsone7245742012-09-05 17:12:55 -07005144 return status;
5145}
5146
5147
Jeff Johnson295189b2012-06-20 16:38:30 -07005148//Register the module init/exit functions
5149module_init(hdd_module_init);
5150module_exit(hdd_module_exit);
5151
5152MODULE_LICENSE("Dual BSD/GPL");
5153MODULE_AUTHOR("Qualcomm Atheros, Inc.");
5154MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
5155
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005156module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
5157 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07005158
5159module_param_call(fwpath, fwpath_changed_handler, param_get_string, fwpath,
5160 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);