blob: a020d0f91273266f890e2c63ae90a8cbcfdc3b88 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/*========================================================================
43
44 \file wlan_hdd_main.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
54/**=========================================================================
55
56 EDIT HISTORY FOR FILE
57
58
59 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
61
62
63 $Header:$ $DateTime: $ $Author: $
64
65
66 when who what, where, why
67 -------- --- --------------------------------------------------------
68 04/5/09 Shailender Created module.
69 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
70 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
71 ==========================================================================*/
72
73/*--------------------------------------------------------------------------
74 Include Files
75 ------------------------------------------------------------------------*/
76//#include <wlan_qct_driver.h>
77#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070078#include <vos_api.h>
79#include <vos_sched.h>
80#include <vos_power.h>
81#include <linux/etherdevice.h>
82#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070083#ifdef ANI_BUS_TYPE_PLATFORM
84#include <linux/wcnss_wlan.h>
85#endif //ANI_BUS_TYPE_PLATFORM
86#ifdef ANI_BUS_TYPE_PCI
87#include "wcnss_wlan.h"
88#endif /* ANI_BUS_TYPE_PCI */
89#include <wlan_hdd_tx_rx.h>
90#include <palTimer.h>
91#include <wniApi.h>
92#include <wlan_nlink_srv.h>
93#include <wlan_btc_svc.h>
94#include <wlan_hdd_cfg.h>
95#include <wlan_ptt_sock_svc.h>
96#include <wlan_hdd_wowl.h>
97#include <wlan_hdd_misc.h>
98#include <wlan_hdd_wext.h>
99#ifdef WLAN_BTAMP_FEATURE
100#include <bap_hdd_main.h>
101#include <bapInternal.h>
102#endif // WLAN_BTAMP_FEATURE
103
Jeff Johnson295189b2012-06-20 16:38:30 -0700104#include <linux/wireless.h>
105#include <net/cfg80211.h>
106#include "wlan_hdd_cfg80211.h"
107#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700108#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700109int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include "sapApi.h"
111#include <linux/semaphore.h>
112#include <mach/subsystem_restart.h>
113#include <wlan_hdd_hostapd.h>
114#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700115#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700116#include "wlan_hdd_dev_pwr.h"
117#ifdef WLAN_BTAMP_FEATURE
118#include "bap_hdd_misc.h"
119#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700120#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700121#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800122#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530123#ifdef FEATURE_WLAN_TDLS
124#include "wlan_hdd_tdls.h"
125#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700126
127#ifdef MODULE
128#define WLAN_MODULE_NAME module_name(THIS_MODULE)
129#else
130#define WLAN_MODULE_NAME "wlan"
131#endif
132
133#ifdef TIMER_MANAGER
134#define TIMER_MANAGER_STR " +TIMER_MANAGER"
135#else
136#define TIMER_MANAGER_STR ""
137#endif
138
139#ifdef MEMORY_DEBUG
140#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
141#else
142#define MEMORY_DEBUG_STR ""
143#endif
144
145/* the Android framework expects this param even though we don't use it */
146#define BUF_LEN 20
147static char fwpath[BUF_LEN];
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700148#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700149static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700150#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700151
Jeff Johnsone7245742012-09-05 17:12:55 -0700152/*
153 * The rate at which the driver sends RESTART event to supplicant
154 * once the function 'vos_wlanRestart()' is called
155 *
156 */
157#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
158#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800159#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700160static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700161#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700162/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700163static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700164
165//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700166static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
167static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
168static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
169void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800170void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700171
Jeff Johnson295189b2012-06-20 16:38:30 -0700172v_U16_t hdd_select_queue(struct net_device *dev,
173 struct sk_buff *skb);
174
175#ifdef WLAN_FEATURE_PACKET_FILTERING
176static void hdd_set_multicast_list(struct net_device *dev);
177#endif
178
179void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
180
181extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800182#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
183void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
184static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
185static VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
186#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700187static int hdd_netdev_notifier_call(struct notifier_block * nb,
188 unsigned long state,
189 void *ndev)
190{
191 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700192 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
193 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -0700194#ifdef WLAN_BTAMP_FEATURE
195 VOS_STATUS status;
196 hdd_context_t *pHddCtx;
197#endif
198
199 //Make sure that this callback corresponds to our device.
200 if((strncmp( dev->name, "wlan", 4 )) &&
Jeff Johnsone7245742012-09-05 17:12:55 -0700201 (strncmp( dev->name, "p2p", 3))
Jeff Johnson295189b2012-06-20 16:38:30 -0700202 )
203 return NOTIFY_DONE;
204
Jeff Johnson295189b2012-06-20 16:38:30 -0700205 if (!dev->ieee80211_ptr)
206 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700207
Jeff Johnson295189b2012-06-20 16:38:30 -0700208
209 if(NULL == pAdapter)
210 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800211 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700212 VOS_ASSERT(0);
213 return NOTIFY_DONE;
214 }
215
216 hddLog(VOS_TRACE_LEVEL_INFO,"%s: New Net Device State = %lu", __func__, state);
217
218 switch (state) {
219 case NETDEV_REGISTER:
220 break;
221
222 case NETDEV_UNREGISTER:
223 break;
224
225 case NETDEV_UP:
226 break;
227
228 case NETDEV_DOWN:
229 break;
230
231 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700232 if(TRUE == pAdapter->isLinkUpSvcNeeded)
233 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700234 break;
235
236 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700237 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700238 {
239 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800240 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700241 hdd_abort_mac_scan(pAdapter->pHddCtx);
242 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800243 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700244 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
245 if(!result)
246 {
247 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800248 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700249 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700250 }
251 }
252 else
253 {
254 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700255 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700256 }
257#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700258 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700259 status = WLANBAP_StopAmp();
260 if(VOS_STATUS_SUCCESS != status )
261 {
262 pHddCtx->isAmpAllowed = VOS_TRUE;
263 hddLog(VOS_TRACE_LEVEL_FATAL,
264 "%s: Failed to stop AMP", __func__);
265 }
266 else
267 {
268 //a state m/c implementation in PAL is TBD to avoid this delay
269 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700270 if ( pHddCtx->isAmpAllowed )
271 {
272 WLANBAP_DeregisterFromHCI();
273 pHddCtx->isAmpAllowed = VOS_FALSE;
274 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700275 }
276#endif //WLAN_BTAMP_FEATURE
277 break;
278
279 default:
280 break;
281 }
282
283 return NOTIFY_DONE;
284}
285
286struct notifier_block hdd_netdev_notifier = {
287 .notifier_call = hdd_netdev_notifier_call,
288};
289
290/*---------------------------------------------------------------------------
291 * Function definitions
292 *-------------------------------------------------------------------------*/
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800293int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700294void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
295void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700296//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700297static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700298#ifndef MODULE
299/* current con_mode - used only for statically linked driver
300 * con_mode is changed by userspace to indicate a mode change which will
301 * result in calling the module exit and init functions. The module
302 * exit function will clean up based on the value of con_mode prior to it
303 * being changed by userspace. So curr_con_mode records the current con_mode
304 * for exit when con_mode becomes the next mode for init
305 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700306static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700307#endif
308
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800309/**---------------------------------------------------------------------------
310
311 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
312
313 Called immediately after the cfg.ini is read in order to configure
314 the desired trace levels.
315
316 \param - moduleId - module whose trace level is being configured
317 \param - bitmask - bitmask of log levels to be enabled
318
319 \return - void
320
321 --------------------------------------------------------------------------*/
322static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
323{
324 wpt_tracelevel level;
325
326 /* if the bitmask is the default value, then a bitmask was not
327 specified in cfg.ini, so leave the logging level alone (it
328 will remain at the "compiled in" default value) */
329 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
330 {
331 return;
332 }
333
334 /* a mask was specified. start by disabling all logging */
335 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
336
337 /* now cycle through the bitmask until all "set" bits are serviced */
338 level = VOS_TRACE_LEVEL_FATAL;
339 while (0 != bitmask)
340 {
341 if (bitmask & 1)
342 {
343 vos_trace_setValue(moduleId, level, 1);
344 }
345 level++;
346 bitmask >>= 1;
347 }
348}
349
350
Jeff Johnson295189b2012-06-20 16:38:30 -0700351/**---------------------------------------------------------------------------
352
353 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
354
355 Called immediately after the cfg.ini is read in order to configure
356 the desired trace levels in the WDI.
357
358 \param - moduleId - module whose trace level is being configured
359 \param - bitmask - bitmask of log levels to be enabled
360
361 \return - void
362
363 --------------------------------------------------------------------------*/
364static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
365{
366 wpt_tracelevel level;
367
368 /* if the bitmask is the default value, then a bitmask was not
369 specified in cfg.ini, so leave the logging level alone (it
370 will remain at the "compiled in" default value) */
371 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
372 {
373 return;
374 }
375
376 /* a mask was specified. start by disabling all logging */
377 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
378
379 /* now cycle through the bitmask until all "set" bits are serviced */
380 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
381 while (0 != bitmask)
382 {
383 if (bitmask & 1)
384 {
385 wpalTraceSetLevel(moduleId, level, 1);
386 }
387 level++;
388 bitmask >>= 1;
389 }
390}
Jeff Johnson295189b2012-06-20 16:38:30 -0700391
392int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
393{
394 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
395 hdd_priv_data_t priv_data;
396 tANI_U8 *command = NULL;
397 int ret = 0;
398
399 if (NULL == pAdapter)
400 {
401 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700402 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700403 ret = -ENODEV;
404 goto exit;
405 }
406
Jeff Johnsone7245742012-09-05 17:12:55 -0700407 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700408 {
409 ret = -EINVAL;
410 goto exit;
411 }
412
413 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
414 {
415 ret = -EFAULT;
416 goto exit;
417 }
418
419 command = kmalloc(priv_data.total_len, GFP_KERNEL);
420 if (!command)
421 {
422 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700423 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700424 ret = -ENOMEM;
425 goto exit;
426 }
427
428 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
429 {
430 ret = -EFAULT;
431 goto exit;
432 }
433
434 if ((SIOCDEVPRIVATE + 1) == cmd)
435 {
436 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
437
438 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700439 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700440
441 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
442 {
443 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
444 sizeof(tSirMacAddr)))
445 {
446 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700447 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700448 ret = -EFAULT;
449 }
450 }
Amar Singhal0974e402013-02-12 14:27:46 -0800451 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700452 {
Amar Singhal0974e402013-02-12 14:27:46 -0800453 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700454 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800455
Jeff Johnson295189b2012-06-20 16:38:30 -0700456 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800457
458 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700459 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700460 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800461 "%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 -0700462 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800463 ret = hdd_setBand_helper(dev, ptr);
464 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700465 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
466 {
467 char *country_code;
468
469 country_code = command + 8;
470 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
471 pAdapter, pHddCtx->pvosContext);
472 if( 0 != ret )
473 {
474 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
475 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
476
477 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700478 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800479#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
480 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
481 {
482 tANI_U8 *value = command;
483 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
484 tANI_U8 revision = 0;
485 eHalStatus status = eHAL_STATUS_SUCCESS;
486 v_REGDOMAIN_t regId;
487
488 status = hdd_parse_countryrev(value, countryCode, &revision);
489 if (eHAL_STATUS_SUCCESS != status)
490 {
491 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
492 "%s: Failed to parse country revision information", __func__);
493 ret = -EINVAL;
494 goto exit;
495 }
496
497 /* Validate country code */
498 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
499 if (eHAL_STATUS_SUCCESS != status)
500 {
501 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
502 "%s: Invalid country code %s", __func__, countryCode);
503 ret = -EINVAL;
504 goto exit;
505 }
506
507 /* Validate revision */
508 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
509 {
510 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
511 "%s: Invalid revision %d", __func__, revision);
512 ret = -EINVAL;
513 goto exit;
514 }
515
516 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
517 pAdapter, pHddCtx->pvosContext);
518 if (0 != ret)
519 {
520 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
521 "%s: SME Change Country code fail ret=%d", __func__, ret);
522 ret = -EINVAL;
523 goto exit;
524 }
525
526 if (0 == strncmp(countryCode, "KR", 2))
527 {
528 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
529 revision);
530 if (eHAL_STATUS_SUCCESS != status)
531 {
532 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
533 "%s: Failed to build valid channel list", __func__);
534 ret = -EINVAL;
535 goto exit;
536 }
537 }
538 }
539#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700540 /*
541 command should be a string having format
542 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
543 */
Amar Singhal0974e402013-02-12 14:27:46 -0800544 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700545 {
Amar Singhal0974e402013-02-12 14:27:46 -0800546 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700547
548 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700549 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700550
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800551 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700552 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800553 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
554 {
555 int suspend = 0;
556 tANI_U8 *ptr = (tANI_U8*)command + 15;
557
558 suspend = *ptr - '0';
559 hdd_set_wlan_suspend_mode(suspend);
560 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800561#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
562 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
563 {
564 tANI_U8 *value = command;
565 int rssi = 0;
566 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
567 eHalStatus status = eHAL_STATUS_SUCCESS;
568
569 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
570 value = value + 15;
571
572 sscanf(value, "%d", &rssi);
573 lookUpThreshold = abs(rssi);
574 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
575 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
576 {
577 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
578 "Neighbor lookup threshold value %d is out of range"
579 " (Min: %d Max: %d)", lookUpThreshold,
580 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
581 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
582 ret = -EINVAL;
583 goto exit;
584 }
585
586 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
587 "%s: Received Command to Set Roam trigger"
588 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
589
590 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
591 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
592 if (eHAL_STATUS_SUCCESS != status)
593 {
594 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
595 "%s: Failed to set roam trigger, try again", __func__);
596 ret = -EPERM;
597 goto exit;
598 }
599
600 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
601 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
602 }
603 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
604 {
605 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
606 int rssi = (-1) * lookUpThreshold;
607 char extra[32];
608 tANI_U8 len = 0;
609
610 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
611 if (copy_to_user(priv_data.buf, &extra, len + 1))
612 {
613 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
614 "%s: failed to copy data to user buffer", __func__);
615 ret = -EFAULT;
616 goto exit;
617 }
618 }
619 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
620 {
621 tANI_U8 *value = command;
622 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
623 /* input refresh period is in terms of seconds */
624 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
625 value = value + 18;
626 /* Convert the value from ascii to integer */
627 ret = kstrtou16(value, 10, &neighborScanRefreshPeriod);
628 if (ret < 0)
629 {
630 /* If the input value is greater than max value of datatype, then also
631 kstrtou16 fails */
632 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
633 "%s: kstrtou16 failed ",
634 "Input value may be out of range[%d - %d]",
635 __func__,
636 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
637 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
638 ret = -EINVAL;
639 goto exit;
640 }
641
642 neighborScanRefreshPeriod = neighborScanRefreshPeriod * 1000;
643 if ((neighborScanRefreshPeriod < CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN) ||
644 (neighborScanRefreshPeriod > CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX))
645 {
646 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
647 "Neighbor scan results refresh period value %d is out of range"
648 " (Min: %d Max: %d)", neighborScanRefreshPeriod,
649 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
650 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
651 ret = -EINVAL;
652 goto exit;
653 }
654
655 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
656 "%s: Received Command to Set roam scan period"
657 " (Neighbor Scan refresh period) = %d", __func__, neighborScanRefreshPeriod);
658
659 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborScanRefreshPeriod;
660 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
661 }
662 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
663 {
664 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
665 char extra[32];
666 tANI_U8 len = 0;
667
668 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
669 /* Returned value is in units of seconds */
670 if (copy_to_user(priv_data.buf, &extra, len + 1))
671 {
672 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
673 "%s: failed to copy data to user buffer", __func__);
674 ret = -EFAULT;
675 goto exit;
676 }
677 }
678#endif
679#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
680 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
681 {
682 tANI_U8 *value = command;
683 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
684
685 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
686 value = value + 13;
687 /* Convert the value from ascii to integer */
688 ret = kstrtou8(value, 10, &roamRssiDiff);
689 if (ret < 0)
690 {
691 /* If the input value is greater than max value of datatype, then also
692 kstrtou8 fails */
693 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
694 "%s: kstrtou8 failed range [%d - %d]", __func__,
695 CFG_ROAM_RSSI_DIFF_MIN,
696 CFG_ROAM_RSSI_DIFF_MAX);
697 ret = -EINVAL;
698 goto exit;
699 }
700
701 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
702 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
703 {
704 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
705 "Roam rssi diff value %d is out of range"
706 " (Min: %d Max: %d)", roamRssiDiff,
707 CFG_ROAM_RSSI_DIFF_MIN,
708 CFG_ROAM_RSSI_DIFF_MAX);
709 ret = -EINVAL;
710 goto exit;
711 }
712
713 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
714 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
715
716 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
717 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
718 }
719 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
720 {
721 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
722 char extra[32];
723 tANI_U8 len = 0;
724
725 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
726 if (copy_to_user(priv_data.buf, &extra, len + 1))
727 {
728 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
729 "%s: failed to copy data to user buffer", __func__);
730 ret = -EFAULT;
731 goto exit;
732 }
733 }
734#endif
735#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
736 else if (strncmp(command, "GETBAND", 7) == 0)
737 {
738 int band = -1;
739 char extra[32];
740 tANI_U8 len = 0;
741 hdd_getBand_helper(pHddCtx, &band);
742
743 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
744 if (copy_to_user(priv_data.buf, &extra, len + 1))
745 {
746 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
747 "%s: failed to copy data to user buffer", __func__);
748 ret = -EFAULT;
749 goto exit;
750 }
751 }
752 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
753 {
754 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
755 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
756 tANI_U8 revision = 0;
757 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
758 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
759 char extra[32] = {0};
760 tANI_U8 len = 0;
761
762 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
763 {
764 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
765 "%s: failed to get country code", __func__);
766 ret = -EFAULT;
767 goto exit;
768 }
769 pBuf[uBufLen] = '\0';
770 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
771
772 if (0 == strncmp(pBuf, "KR", 2))
773 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
774 else
775 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
776
777 if (copy_to_user(priv_data.buf, &extra, len + 1))
778 {
779 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
780 "%s: failed to copy data to user buffer", __func__);
781 ret = -EFAULT;
782 goto exit;
783 }
784 }
785 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
786 {
787 tANI_U8 *value = command;
788 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
789 tANI_U8 numChannels = 0;
790 eHalStatus status = eHAL_STATUS_SUCCESS;
791
792 status = hdd_parse_channellist(value, ChannelList, &numChannels);
793 if (eHAL_STATUS_SUCCESS != status)
794 {
795 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
796 "%s: Failed to parse channel list information", __func__);
797 ret = -EINVAL;
798 goto exit;
799 }
800
801 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
802 {
803 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
804 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
805 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
806 ret = -EINVAL;
807 goto exit;
808 }
809 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
810 numChannels);
811 if (eHAL_STATUS_SUCCESS != status)
812 {
813 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
814 "%s: Failed to update channel list information", __func__);
815 ret = -EINVAL;
816 goto exit;
817 }
818 }
819 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
820 {
821 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
822 tANI_U8 numChannels = 0;
823 tANI_U8 len = 0, j = 0;
824 char extra[128] = {0};
825
826 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
827 ChannelList, &numChannels ))
828 {
829 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
830 "%s: failed to get roam scan channel list", __func__);
831 ret = -EFAULT;
832 goto exit;
833 }
834 /* output channel list is of the format
835 [Number of roam scan channels][Channel1][Channel2]... */
836 /* copy the number of channels in the 0th index */
837 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
838 for (j = 0; (j < numChannels); j++)
839 {
840 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
841 }
842
843 if (copy_to_user(priv_data.buf, &extra, len + 1))
844 {
845 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
846 "%s: failed to copy data to user buffer", __func__);
847 ret = -EFAULT;
848 goto exit;
849 }
850 }
851#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700852 else {
853 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
854 __func__, command);
855 }
856
Jeff Johnson295189b2012-06-20 16:38:30 -0700857 }
858exit:
859 if (command)
860 {
861 kfree(command);
862 }
863 return ret;
864}
865
Srinivas Girigowdade697412013-02-14 16:31:48 -0800866#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
867void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
868{
869 eCsrBand band = -1;
870 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
871 switch (band)
872 {
873 case eCSR_BAND_ALL:
874 *pBand = WLAN_HDD_UI_BAND_AUTO;
875 break;
876
877 case eCSR_BAND_24:
878 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
879 break;
880
881 case eCSR_BAND_5G:
882 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
883 break;
884
885 default:
886 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
887 *pBand = -1;
888 break;
889 }
890}
891
892/**---------------------------------------------------------------------------
893
894 \brief hdd_parse_countryrev() - HDD Parse country code revision
895
896 This function parses the country code revision passed in the format
897 SETCOUNTRYREV<space><Country code><space>revision
898
899 \param - pValue Pointer to input country code revision
900 \param - pCountryCode Pointer to local output array to record country code
901 \param - pRevision Pointer to store revision integer number
902
903 \return - 0 for success non-zero for failure
904
905 --------------------------------------------------------------------------*/
906VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
907{
908 tANI_U8 *inPtr = pValue;
909 int tempInt;
910
911 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
912 /*no argument after the command*/
913 if (NULL == inPtr)
914 {
915 return -EINVAL;
916 }
917
918 /*no space after the command*/
919 else if (SPACE_ASCII_VALUE != *inPtr)
920 {
921 return -EINVAL;
922 }
923
924 /*removing empty spaces*/
925 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
926
927 /*no argument followed by spaces*/
928 if ('\0' == *inPtr)
929 {
930 return -EINVAL;
931 }
932
933 /*getting the first argument ie the country code */
934 sscanf(inPtr, "%s ", pCountryCode);
935
936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
937 "Country code is : %s", pCountryCode);
938
939 /*inPtr pointing to the beginning of first space after country code */
940 inPtr = strpbrk( inPtr, " " );
941 /*no revision number after the country code argument */
942 if (NULL == inPtr)
943 {
944 return -EINVAL;
945 }
946
947 inPtr++;
948
949 /*removing empty space*/
950 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
951
952 /*no channel list after the number of channels argument and spaces*/
953 if (0 == strncmp(pCountryCode, "KR", 2))
954 {
955 if ('\0' == *inPtr)
956 {
957 return -EINVAL;
958 }
959
960 sscanf(inPtr, "%d", &tempInt);
961 *pRevision = tempInt;
962 }
963 else
964 {
965 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
966 "Revision input is required only for Country KR");
967 return -EINVAL;
968 }
969 return VOS_STATUS_SUCCESS;
970}
971
972/**---------------------------------------------------------------------------
973
974 \brief hdd_parse_channellist() - HDD Parse channel list
975
976 This function parses the channel list passed in the format
977 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
978
979 \param - pValue Pointer to input channel list
980 \param - ChannelList Pointer to local output array to record channel list
981 \param - pNumChannels Pointer to number of roam scan channels
982
983 \return - 0 for success non-zero for failure
984
985 --------------------------------------------------------------------------*/
986VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
987{
988 tANI_U8 *inPtr = pValue;
989 int tempInt;
990 int j = 0;
991 int v = 0;
992 char buf[32];
993
994 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
995 /*no argument after the command*/
996 if (NULL == inPtr)
997 {
998 return -EINVAL;
999 }
1000
1001 /*no space after the command*/
1002 else if (SPACE_ASCII_VALUE != *inPtr)
1003 {
1004 return -EINVAL;
1005 }
1006
1007 /*removing empty spaces*/
1008 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
1009
1010 /*no argument followed by spaces*/
1011 if ('\0' == *inPtr)
1012 {
1013 return -EINVAL;
1014 }
1015
1016 /*getting the first argument ie the number of channels*/
1017 sscanf(inPtr, "%s ", buf);
1018 v = kstrtos32(buf, 10, &tempInt);
1019 if ( v < 0) return -EINVAL;
1020
1021 *pNumChannels = tempInt;
1022
1023 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1024 "Number of channels are: %d", *pNumChannels);
1025
1026 for (j = 0; j < (*pNumChannels); j++)
1027 {
1028 /*inPtr pointing to the beginning of first space after number of channels*/
1029 inPtr = strpbrk( inPtr, " " );
1030 /*no channel list after the number of channels argument*/
1031 if (NULL == inPtr)
1032 {
1033 return -EINVAL;
1034 }
1035
1036 /*removing empty space*/
1037 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1038
1039 /*no channel list after the number of channels argument and spaces*/
1040 if ( '\0' == *inPtr )
1041 {
1042 return -EINVAL;
1043 }
1044
1045 sscanf(inPtr, "%s ", buf);
1046 v = kstrtos32(buf, 10, &tempInt);
1047 if ( v < 0) return -EINVAL;
1048 pChannelList[j] = tempInt;
1049
1050 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1051 "Channel %d added to preferred channel list",
1052 pChannelList[j] );
1053 }
1054
1055 /* if the actual number of channels passed are more than
1056 pNumChannels then ignore the rest; take only pNumChannels */
1057 return VOS_STATUS_SUCCESS;
1058}
1059
1060#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001061/**---------------------------------------------------------------------------
1062
1063 \brief hdd_open() - HDD Open function
1064
1065 This is called in response to ifconfig up
1066
1067 \param - dev Pointer to net_device structure
1068
1069 \return - 0 for success non-zero for failure
1070
1071 --------------------------------------------------------------------------*/
1072int hdd_open (struct net_device *dev)
1073{
1074 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1075 hdd_context_t *pHddCtx;
1076 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1077 VOS_STATUS status;
1078 v_BOOL_t in_standby = TRUE;
1079
1080 if (NULL == pAdapter)
1081 {
1082 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001083 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001084 return -ENODEV;
1085 }
1086
1087 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1088 if (NULL == pHddCtx)
1089 {
1090 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001091 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001092 return -ENODEV;
1093 }
1094
1095 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1096 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1097 {
1098 if( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
1099 {
1100 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of "
1101 "standby", __func__, pAdapter->device_mode);
1102 in_standby = FALSE;
1103 break;
1104 }
1105 else
1106 {
1107 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1108 pAdapterNode = pNext;
1109 }
1110 }
1111
1112 if (TRUE == in_standby)
1113 {
1114 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
1115 {
1116 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
1117 "wlan out of power save", __func__);
1118 return -EINVAL;
1119 }
1120 }
1121
1122 pAdapter->event_flags |= DEVICE_IFACE_OPENED;
1123 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
1124 {
1125 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001126 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001127 /* Enable TX queues only when we are connected */
1128 netif_tx_start_all_queues(dev);
1129 }
1130
1131 return 0;
1132}
1133
1134int hdd_mon_open (struct net_device *dev)
1135{
1136 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1137
1138 if(pAdapter == NULL) {
1139 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001140 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001141 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001142 }
1143
1144 netif_start_queue(dev);
1145
1146 return 0;
1147}
1148/**---------------------------------------------------------------------------
1149
1150 \brief hdd_stop() - HDD stop function
1151
1152 This is called in response to ifconfig down
1153
1154 \param - dev Pointer to net_device structure
1155
1156 \return - 0 for success non-zero for failure
1157
1158 --------------------------------------------------------------------------*/
1159
1160int hdd_stop (struct net_device *dev)
1161{
1162 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1163 hdd_context_t *pHddCtx;
1164 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1165 VOS_STATUS status;
1166 v_BOOL_t enter_standby = TRUE;
1167
1168 ENTER();
1169
1170 if (NULL == pAdapter)
1171 {
1172 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001173 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001174 return -ENODEV;
1175 }
1176
1177 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1178 if (NULL == pHddCtx)
1179 {
1180 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001181 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001182 return -ENODEV;
1183 }
1184
1185 pAdapter->event_flags &= ~(DEVICE_IFACE_OPENED);
1186 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
1187 netif_tx_disable(pAdapter->dev);
1188 netif_carrier_off(pAdapter->dev);
1189
1190
1191 /* SoftAP ifaces should never go in power save mode
1192 making sure same here. */
1193 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
1194 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
1195#ifdef WLAN_FEATURE_P2P
1196 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
1197#endif
1198 )
1199 {
1200 /* SoftAP mode, so return from here */
1201 EXIT();
1202 return 0;
1203 }
1204
1205 /* Find if any iface is up then
1206 if any iface is up then can't put device to sleep/ power save mode. */
1207 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1208 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1209 {
1210 if ( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
1211 {
1212 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
1213 "put device to sleep", __func__, pAdapter->device_mode);
1214 enter_standby = FALSE;
1215 break;
1216 }
1217 else
1218 {
1219 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1220 pAdapterNode = pNext;
1221 }
1222 }
1223
1224 if (TRUE == enter_standby)
1225 {
1226 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
1227 "entering standby", __func__);
1228 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
1229 {
1230 /*log and return success*/
1231 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
1232 "wlan in power save", __func__);
1233 }
1234 }
1235
1236 EXIT();
1237 return 0;
1238}
1239
1240/**---------------------------------------------------------------------------
1241
1242 \brief hdd_uninit() - HDD uninit function
1243
1244 This is called during the netdev unregister to uninitialize all data
1245associated with the device
1246
1247 \param - dev Pointer to net_device structure
1248
1249 \return - void
1250
1251 --------------------------------------------------------------------------*/
1252static void hdd_uninit (struct net_device *dev)
1253{
1254 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1255
1256 ENTER();
1257
1258 do
1259 {
1260 if (NULL == pAdapter)
1261 {
1262 hddLog(VOS_TRACE_LEVEL_FATAL,
1263 "%s: NULL pAdapter", __func__);
1264 break;
1265 }
1266
1267 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1268 {
1269 hddLog(VOS_TRACE_LEVEL_FATAL,
1270 "%s: Invalid magic", __func__);
1271 break;
1272 }
1273
1274 if (NULL == pAdapter->pHddCtx)
1275 {
1276 hddLog(VOS_TRACE_LEVEL_FATAL,
1277 "%s: NULL pHddCtx", __func__);
1278 break;
1279 }
1280
1281 if (dev != pAdapter->dev)
1282 {
1283 hddLog(VOS_TRACE_LEVEL_FATAL,
1284 "%s: Invalid device reference", __func__);
1285 /* we haven't validated all cases so let this go for now */
1286 }
1287
1288 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
1289
1290 /* after uninit our adapter structure will no longer be valid */
1291 pAdapter->dev = NULL;
1292 pAdapter->magic = 0;
1293 } while (0);
1294
1295 EXIT();
1296}
1297
1298/**---------------------------------------------------------------------------
1299
1300 \brief hdd_release_firmware() -
1301
1302 This function calls the release firmware API to free the firmware buffer.
1303
1304 \param - pFileName Pointer to the File Name.
1305 pCtx - Pointer to the adapter .
1306
1307
1308 \return - 0 for success, non zero for failure
1309
1310 --------------------------------------------------------------------------*/
1311
1312VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
1313{
1314 VOS_STATUS status = VOS_STATUS_SUCCESS;
1315 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1316 ENTER();
1317
1318
1319 if (!strcmp(WLAN_FW_FILE, pFileName)) {
1320
1321 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
1322
1323 if(pHddCtx->fw) {
1324 release_firmware(pHddCtx->fw);
1325 pHddCtx->fw = NULL;
1326 }
1327 else
1328 status = VOS_STATUS_E_FAILURE;
1329 }
1330 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
1331 if(pHddCtx->nv) {
1332 release_firmware(pHddCtx->nv);
1333 pHddCtx->nv = NULL;
1334 }
1335 else
1336 status = VOS_STATUS_E_FAILURE;
1337
1338 }
1339
1340 EXIT();
1341 return status;
1342}
1343
1344/**---------------------------------------------------------------------------
1345
1346 \brief hdd_request_firmware() -
1347
1348 This function reads the firmware file using the request firmware
1349 API and returns the the firmware data and the firmware file size.
1350
1351 \param - pfileName - Pointer to the file name.
1352 - pCtx - Pointer to the adapter .
1353 - ppfw_data - Pointer to the pointer of the firmware data.
1354 - pSize - Pointer to the file size.
1355
1356 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
1357
1358 --------------------------------------------------------------------------*/
1359
1360
1361VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
1362{
1363 int status;
1364 VOS_STATUS retval = VOS_STATUS_SUCCESS;
1365 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1366 ENTER();
1367
1368 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
1369
1370 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
1371
1372 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1373 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
1374 __func__, pfileName);
1375 retval = VOS_STATUS_E_FAILURE;
1376 }
1377
1378 else {
1379 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
1380 *pSize = pHddCtx->fw->size;
1381 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
1382 __func__, *pSize);
1383 }
1384 }
1385 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
1386
1387 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
1388
1389 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
1390 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
1391 __func__, pfileName);
1392 retval = VOS_STATUS_E_FAILURE;
1393 }
1394
1395 else {
1396 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
1397 *pSize = pHddCtx->nv->size;
1398 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
1399 __func__, *pSize);
1400 }
1401 }
1402
1403 EXIT();
1404 return retval;
1405}
1406/**---------------------------------------------------------------------------
1407 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
1408
1409 This is the function invoked by SME to inform the result of a full power
1410 request issued by HDD
1411
1412 \param - callbackcontext - Pointer to cookie
1413 status - result of request
1414
1415 \return - None
1416
1417--------------------------------------------------------------------------*/
1418void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
1419{
1420 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
1421
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001422 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001423 if(&pHddCtx->full_pwr_comp_var)
1424 {
1425 complete(&pHddCtx->full_pwr_comp_var);
1426 }
1427}
1428
1429/**---------------------------------------------------------------------------
1430
1431 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
1432
1433 This is the function invoked by SME to inform the result of BMPS
1434 request issued by HDD
1435
1436 \param - callbackcontext - Pointer to cookie
1437 status - result of request
1438
1439 \return - None
1440
1441--------------------------------------------------------------------------*/
1442void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
1443{
1444
1445 struct completion *completion_var = (struct completion*) callbackContext;
1446
1447 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
1448 if(completion_var != NULL)
1449 {
1450 complete(completion_var);
1451 }
1452}
1453
1454/**---------------------------------------------------------------------------
1455
1456 \brief hdd_get_cfg_file_size() -
1457
1458 This function reads the configuration file using the request firmware
1459 API and returns the configuration file size.
1460
1461 \param - pCtx - Pointer to the adapter .
1462 - pFileName - Pointer to the file name.
1463 - pBufSize - Pointer to the buffer size.
1464
1465 \return - 0 for success, non zero for failure
1466
1467 --------------------------------------------------------------------------*/
1468
1469VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
1470{
1471 int status;
1472 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1473
1474 ENTER();
1475
1476 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
1477
1478 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1479 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
1480 status = VOS_STATUS_E_FAILURE;
1481 }
1482 else {
1483 *pBufSize = pHddCtx->fw->size;
1484 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
1485 release_firmware(pHddCtx->fw);
1486 pHddCtx->fw = NULL;
1487 }
1488
1489 EXIT();
1490 return VOS_STATUS_SUCCESS;
1491}
1492
1493/**---------------------------------------------------------------------------
1494
1495 \brief hdd_read_cfg_file() -
1496
1497 This function reads the configuration file using the request firmware
1498 API and returns the cfg data and the buffer size of the configuration file.
1499
1500 \param - pCtx - Pointer to the adapter .
1501 - pFileName - Pointer to the file name.
1502 - pBuffer - Pointer to the data buffer.
1503 - pBufSize - Pointer to the buffer size.
1504
1505 \return - 0 for success, non zero for failure
1506
1507 --------------------------------------------------------------------------*/
1508
1509VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
1510 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
1511{
1512 int status;
1513 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1514
1515 ENTER();
1516
1517 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
1518
1519 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1520 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
1521 return VOS_STATUS_E_FAILURE;
1522 }
1523 else {
1524 if(*pBufSize != pHddCtx->fw->size) {
1525 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
1526 "file size", __func__);
1527 release_firmware(pHddCtx->fw);
1528 pHddCtx->fw = NULL;
1529 return VOS_STATUS_E_FAILURE;
1530 }
1531 else {
1532 if(pBuffer) {
1533 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
1534 }
1535 release_firmware(pHddCtx->fw);
1536 pHddCtx->fw = NULL;
1537 }
1538 }
1539
1540 EXIT();
1541
1542 return VOS_STATUS_SUCCESS;
1543}
1544
1545/**---------------------------------------------------------------------------
1546
Jeff Johnson295189b2012-06-20 16:38:30 -07001547 \brief hdd_set_mac_address() -
1548
1549 This function sets the user specified mac address using
1550 the command ifconfig wlanX hw ether <mac adress>.
1551
1552 \param - dev - Pointer to the net device.
1553 - addr - Pointer to the sockaddr.
1554 \return - 0 for success, non zero for failure
1555
1556 --------------------------------------------------------------------------*/
1557
1558static int hdd_set_mac_address(struct net_device *dev, void *addr)
1559{
1560 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1561 struct sockaddr *psta_mac_addr = addr;
1562 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1563
1564 ENTER();
1565
1566 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
1567
1568#ifdef HDD_SESSIONIZE
1569 // set the MAC address though the STA ID CFG.
1570 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
1571 (v_U8_t *)&pAdapter->macAddressCurrent,
1572 sizeof( pAdapter->macAddressCurrent ),
1573 hdd_set_mac_addr_cb, VOS_FALSE );
1574#endif
1575
1576 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
1577
1578 EXIT();
1579 return halStatus;
1580}
1581
1582tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
1583{
1584 int i;
1585 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
1586 {
1587 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
1588 break;
1589 }
1590
1591 if( VOS_MAX_CONCURRENCY_PERSONA == i)
1592 return NULL;
1593
1594 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
1595 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
1596}
1597
1598void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
1599{
1600 int i;
1601 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
1602 {
1603 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
1604 {
1605 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
1606 break;
1607 }
1608 }
1609 return;
1610}
1611
1612#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1613 static struct net_device_ops wlan_drv_ops = {
1614 .ndo_open = hdd_open,
1615 .ndo_stop = hdd_stop,
1616 .ndo_uninit = hdd_uninit,
1617 .ndo_start_xmit = hdd_hard_start_xmit,
1618 .ndo_tx_timeout = hdd_tx_timeout,
1619 .ndo_get_stats = hdd_stats,
1620 .ndo_do_ioctl = hdd_ioctl,
1621 .ndo_set_mac_address = hdd_set_mac_address,
1622 .ndo_select_queue = hdd_select_queue,
1623#ifdef WLAN_FEATURE_PACKET_FILTERING
1624#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
1625 .ndo_set_rx_mode = hdd_set_multicast_list,
1626#else
1627 .ndo_set_multicast_list = hdd_set_multicast_list,
1628#endif //LINUX_VERSION_CODE
1629#endif
1630 };
Jeff Johnson295189b2012-06-20 16:38:30 -07001631 static struct net_device_ops wlan_mon_drv_ops = {
1632 .ndo_open = hdd_mon_open,
1633 .ndo_stop = hdd_stop,
1634 .ndo_uninit = hdd_uninit,
1635 .ndo_start_xmit = hdd_mon_hard_start_xmit,
1636 .ndo_tx_timeout = hdd_tx_timeout,
1637 .ndo_get_stats = hdd_stats,
1638 .ndo_do_ioctl = hdd_ioctl,
1639 .ndo_set_mac_address = hdd_set_mac_address,
1640 };
Jeff Johnson295189b2012-06-20 16:38:30 -07001641
1642#endif
1643
1644void hdd_set_station_ops( struct net_device *pWlanDev )
1645{
1646#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1647 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
1648 pWlanDev->netdev_ops = &wlan_drv_ops;
1649#else
1650 pWlanDev->open = hdd_open;
1651 pWlanDev->stop = hdd_stop;
1652 pWlanDev->uninit = hdd_uninit;
1653 pWlanDev->hard_start_xmit = NULL;
1654 pWlanDev->tx_timeout = hdd_tx_timeout;
1655 pWlanDev->get_stats = hdd_stats;
1656 pWlanDev->do_ioctl = hdd_ioctl;
1657 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
1658 pWlanDev->set_mac_address = hdd_set_mac_address;
1659#endif
1660}
1661
Jeff Johnsoneed415b2013-01-18 16:11:20 -08001662static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07001663{
1664 struct net_device *pWlanDev = NULL;
1665 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001666 /*
1667 * cfg80211 initialization and registration....
1668 */
1669 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
1670
Jeff Johnson295189b2012-06-20 16:38:30 -07001671 if(pWlanDev != NULL)
1672 {
1673
1674 //Save the pointer to the net_device in the HDD adapter
1675 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
1676
Jeff Johnson295189b2012-06-20 16:38:30 -07001677 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
1678
1679 pAdapter->dev = pWlanDev;
1680 pAdapter->pHddCtx = pHddCtx;
1681 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
1682
1683 init_completion(&pAdapter->session_open_comp_var);
1684 init_completion(&pAdapter->session_close_comp_var);
1685 init_completion(&pAdapter->disconnect_comp_var);
1686 init_completion(&pAdapter->linkup_event_var);
1687 init_completion(&pAdapter->cancel_rem_on_chan_var);
1688 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001689#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1690 init_completion(&pAdapter->offchannel_tx_event);
1691#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001692 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08001693#ifdef FEATURE_WLAN_TDLS
1694 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001695 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08001696#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001697 init_completion(&pHddCtx->mc_sus_event_var);
1698 init_completion(&pHddCtx->tx_sus_event_var);
1699
Jeff Johnson295189b2012-06-20 16:38:30 -07001700 pAdapter->isLinkUpSvcNeeded = FALSE;
1701 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
1702 //Init the net_device structure
1703 strlcpy(pWlanDev->name, name, IFNAMSIZ);
1704
1705 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
1706 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
1707 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
1708 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
1709
1710 hdd_set_station_ops( pAdapter->dev );
1711
1712 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07001713 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
1714 pAdapter->wdev.wiphy = pHddCtx->wiphy;
1715 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07001716 /* set pWlanDev's parent to underlying device */
1717 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
1718 }
1719
1720 return pAdapter;
1721}
1722
1723VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
1724{
1725 struct net_device *pWlanDev = pAdapter->dev;
1726 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1727 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1728 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1729
1730 if( rtnl_lock_held )
1731 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001732 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07001733 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
1734 {
1735 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
1736 return VOS_STATUS_E_FAILURE;
1737 }
1738 }
1739 if (register_netdevice(pWlanDev))
1740 {
1741 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
1742 return VOS_STATUS_E_FAILURE;
1743 }
1744 }
1745 else
1746 {
1747 if(register_netdev(pWlanDev))
1748 {
1749 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
1750 return VOS_STATUS_E_FAILURE;
1751 }
1752 }
1753 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
1754
1755 return VOS_STATUS_SUCCESS;
1756}
1757
1758eHalStatus hdd_smeCloseSessionCallback(void *pContext)
1759{
1760 if(pContext != NULL)
1761 {
1762 clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags);
1763
1764 /* need to make sure all of our scheduled work has completed.
1765 * This callback is called from MC thread context, so it is safe to
1766 * to call below flush workqueue API from here.
1767 */
1768 flush_scheduled_work();
1769 complete(&((hdd_adapter_t*)pContext)->session_close_comp_var);
1770 }
1771 return eHAL_STATUS_SUCCESS;
1772}
1773
1774VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
1775{
1776 struct net_device *pWlanDev = pAdapter->dev;
1777 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1778 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1779 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1780 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1781 int rc = 0;
1782
1783 INIT_COMPLETION(pAdapter->session_open_comp_var);
1784 //Open a SME session for future operation
1785 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
1786 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
1787 if ( !HAL_STATUS_SUCCESS( halStatus ) )
1788 {
1789 hddLog(VOS_TRACE_LEVEL_FATAL,
1790 "sme_OpenSession() failed with status code %08d [x%08lx]",
1791 halStatus, halStatus );
1792 status = VOS_STATUS_E_FAILURE;
1793 goto error_sme_open;
1794 }
1795
1796 //Block on a completion variable. Can't wait forever though.
1797 rc = wait_for_completion_interruptible_timeout(
1798 &pAdapter->session_open_comp_var,
1799 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1800 if (!rc)
1801 {
1802 hddLog(VOS_TRACE_LEVEL_FATAL,
1803 "Session is not opened within timeout period code %08d", rc );
1804 status = VOS_STATUS_E_FAILURE;
1805 goto error_sme_open;
1806 }
1807
1808 // Register wireless extensions
1809 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
1810 {
1811 hddLog(VOS_TRACE_LEVEL_FATAL,
1812 "hdd_register_wext() failed with status code %08d [x%08lx]",
1813 halStatus, halStatus );
1814 status = VOS_STATUS_E_FAILURE;
1815 goto error_register_wext;
1816 }
1817 //Safe to register the hard_start_xmit function again
1818#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1819 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
1820#else
1821 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
1822#endif
1823
1824 //Set the Connection State to Not Connected
1825 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
1826
1827 //Set the default operation channel
1828 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
1829
1830 /* Make the default Auth Type as OPEN*/
1831 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
1832
1833 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
1834 {
1835 hddLog(VOS_TRACE_LEVEL_FATAL,
1836 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
1837 status, status );
1838 goto error_init_txrx;
1839 }
1840
1841 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1842
1843 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
1844 {
1845 hddLog(VOS_TRACE_LEVEL_FATAL,
1846 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
1847 status, status );
1848 goto error_wmm_init;
1849 }
1850
1851 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1852
1853 return VOS_STATUS_SUCCESS;
1854
1855error_wmm_init:
1856 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1857 hdd_deinit_tx_rx(pAdapter);
1858error_init_txrx:
1859 hdd_UnregisterWext(pWlanDev);
1860error_register_wext:
1861 if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
1862 {
1863 INIT_COMPLETION(pAdapter->session_close_comp_var);
1864 if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
1865 pAdapter->sessionId,
1866 hdd_smeCloseSessionCallback, pAdapter ) )
1867 {
1868 //Block on a completion variable. Can't wait forever though.
1869 wait_for_completion_interruptible_timeout(
1870 &pAdapter->session_close_comp_var,
1871 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1872 }
1873}
1874error_sme_open:
1875 return status;
1876}
1877
Jeff Johnson295189b2012-06-20 16:38:30 -07001878void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1879{
1880 hdd_cfg80211_state_t *cfgState;
1881
1882 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1883
1884 if( NULL != cfgState->buf )
1885 {
1886 int rc;
1887 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
1888 rc = wait_for_completion_interruptible_timeout(
1889 &pAdapter->tx_action_cnf_event,
1890 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
1891 if(!rc)
1892 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08001893 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001894 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
1895 }
1896 }
1897 return;
1898}
Jeff Johnson295189b2012-06-20 16:38:30 -07001899
1900void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1901{
1902 ENTER();
1903 switch ( pAdapter->device_mode )
1904 {
1905 case WLAN_HDD_INFRA_STATION:
1906 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07001907 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07001908 {
1909 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1910 {
1911 hdd_deinit_tx_rx( pAdapter );
1912 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1913 }
1914
1915 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
1916 {
1917 hdd_wmm_adapter_close( pAdapter );
1918 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1919 }
1920
Jeff Johnson295189b2012-06-20 16:38:30 -07001921 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001922
1923 break;
1924 }
1925
1926 case WLAN_HDD_SOFTAP:
1927 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07001928 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001929 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001930
1931 hdd_unregister_hostapd(pAdapter);
1932 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07001933 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07001934 break;
1935 }
1936
1937 case WLAN_HDD_MONITOR:
1938 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001939 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07001940 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1941 {
1942 hdd_deinit_tx_rx( pAdapter );
1943 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1944 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001945 if(NULL != pAdapterforTx)
1946 {
1947 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
1948 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001949 break;
1950 }
1951
1952
1953 default:
1954 break;
1955 }
1956
1957 EXIT();
1958}
1959
1960void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
1961{
1962 struct net_device *pWlanDev = pAdapter->dev;
1963
1964 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
1965 if( rtnl_held )
1966 {
1967 unregister_netdevice(pWlanDev);
1968 }
1969 else
1970 {
1971 unregister_netdev(pWlanDev);
1972 }
1973 // note that the pAdapter is no longer valid at this point
1974 // since the memory has been reclaimed
1975 }
1976
1977}
1978
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08001979void hdd_set_pwrparams(hdd_context_t *pHddCtx)
1980{
1981 tSirSetPowerParamsReq powerRequest = { 0 };
1982
1983 powerRequest.uIgnoreDTIM = 1;
1984
1985 if (pHddCtx->cfg_ini->enableModulatedDTIM)
1986 {
1987 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
1988 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
1989 }
1990 else
1991 {
1992 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
1993 }
1994
1995 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
1996 *specified during Enter/Exit BMPS when LCD off*/
1997 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1998 NULL, eANI_BOOLEAN_FALSE);
1999 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2000 NULL, eANI_BOOLEAN_FALSE);
2001
2002 /* switch to the DTIM specified in cfg.ini */
2003 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2004 "Switch to DTIM%d", powerRequest.uListenInterval);
2005 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2006
2007}
2008
2009void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
2010{
2011 /*Switch back to DTIM 1*/
2012 tSirSetPowerParamsReq powerRequest = { 0 };
2013
2014 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
2015 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2016
2017 /* Update ignoreDTIM and ListedInterval in CFG with default values */
2018 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2019 NULL, eANI_BOOLEAN_FALSE);
2020 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2021 NULL, eANI_BOOLEAN_FALSE);
2022
2023 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2024 "Switch to DTIM%d",powerRequest.uListenInterval);
2025 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2026
2027}
2028
Jeff Johnson295189b2012-06-20 16:38:30 -07002029VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
2030{
2031 VOS_STATUS status = VOS_STATUS_SUCCESS;
2032
2033 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2034 {
2035 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2036 }
2037
2038 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2039 {
2040 sme_StartAutoBmpsTimer(pHddCtx->hHal);
2041 }
2042
2043 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2044 {
2045 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2046 }
2047
2048 return status;
2049}
2050
2051VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
2052{
2053 hdd_adapter_t *pAdapter = NULL;
2054 eHalStatus halStatus;
2055 VOS_STATUS status = VOS_STATUS_E_INVAL;
2056 v_BOOL_t disableBmps = FALSE;
2057 v_BOOL_t disableImps = FALSE;
2058
2059 switch(session_type)
2060 {
2061 case WLAN_HDD_INFRA_STATION:
2062 case WLAN_HDD_SOFTAP:
2063#ifdef WLAN_FEATURE_P2P
2064 case WLAN_HDD_P2P_CLIENT:
2065 case WLAN_HDD_P2P_GO:
2066#endif
2067 //Exit BMPS -> Is Sta/P2P Client is already connected
2068 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
2069 if((NULL != pAdapter)&&
2070 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2071 {
2072 disableBmps = TRUE;
2073 }
2074
2075 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
2076 if((NULL != pAdapter)&&
2077 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2078 {
2079 disableBmps = TRUE;
2080 }
2081
2082 //Exit both Bmps and Imps incase of Go/SAP Mode
2083 if((WLAN_HDD_SOFTAP == session_type) ||
2084 (WLAN_HDD_P2P_GO == session_type))
2085 {
2086 disableBmps = TRUE;
2087 disableImps = TRUE;
2088 }
2089
2090 if(TRUE == disableImps)
2091 {
2092 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2093 {
2094 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2095 }
2096 }
2097
2098 if(TRUE == disableBmps)
2099 {
2100 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2101 {
2102 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2103
2104 if(eHAL_STATUS_SUCCESS != halStatus)
2105 {
2106 status = VOS_STATUS_E_FAILURE;
2107 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
2108 VOS_ASSERT(0);
2109 return status;
2110 }
2111 }
2112
2113 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2114 {
2115 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
2116
2117 if(eHAL_STATUS_SUCCESS != halStatus)
2118 {
2119 status = VOS_STATUS_E_FAILURE;
2120 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
2121 VOS_ASSERT(0);
2122 return status;
2123 }
2124 }
2125 }
2126
2127 if((TRUE == disableBmps) ||
2128 (TRUE == disableImps))
2129 {
2130 /* Now, get the chip into Full Power now */
2131 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
2132 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
2133 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
2134
2135 if(halStatus != eHAL_STATUS_SUCCESS)
2136 {
2137 if(halStatus == eHAL_STATUS_PMC_PENDING)
2138 {
2139 //Block on a completion variable. Can't wait forever though
2140 wait_for_completion_interruptible_timeout(
2141 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
2142 }
2143 else
2144 {
2145 status = VOS_STATUS_E_FAILURE;
2146 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
2147 VOS_ASSERT(0);
2148 return status;
2149 }
2150 }
2151
2152 status = VOS_STATUS_SUCCESS;
2153 }
2154
2155 break;
2156 }
2157 return status;
2158}
2159
2160hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002161 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07002162 tANI_U8 rtnl_held )
2163{
2164 hdd_adapter_t *pAdapter = NULL;
2165 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
2166 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2167 VOS_STATUS exitbmpsStatus;
2168
2169 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
2170
2171 //Disable BMPS incase of Concurrency
2172 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
2173
2174 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
2175 {
2176 //Fail to Exit BMPS
2177 VOS_ASSERT(0);
2178 return NULL;
2179 }
2180
2181 switch(session_type)
2182 {
2183 case WLAN_HDD_INFRA_STATION:
2184#ifdef WLAN_FEATURE_P2P
2185 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002186 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002187#endif
2188 {
2189 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2190
2191 if( NULL == pAdapter )
2192 return NULL;
2193
Jeff Johnsone7245742012-09-05 17:12:55 -07002194 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
2195 NL80211_IFTYPE_P2P_CLIENT:
2196 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07002197
Jeff Johnson295189b2012-06-20 16:38:30 -07002198 pAdapter->device_mode = session_type;
2199
2200 status = hdd_init_station_mode( pAdapter );
2201 if( VOS_STATUS_SUCCESS != status )
2202 goto err_free_netdev;
2203
2204 status = hdd_register_interface( pAdapter, rtnl_held );
2205 if( VOS_STATUS_SUCCESS != status )
2206 {
2207 hdd_deinit_adapter(pHddCtx, pAdapter);
2208 goto err_free_netdev;
2209 }
2210 //Stop the Interface TX queue.
2211 netif_tx_disable(pAdapter->dev);
2212 //netif_tx_disable(pWlanDev);
2213 netif_carrier_off(pAdapter->dev);
2214
2215 break;
2216 }
2217
2218#ifdef WLAN_FEATURE_P2P
2219 case WLAN_HDD_P2P_GO:
2220#endif
2221 case WLAN_HDD_SOFTAP:
2222 {
2223 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
2224 if( NULL == pAdapter )
2225 return NULL;
2226
Jeff Johnson295189b2012-06-20 16:38:30 -07002227 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
2228 NL80211_IFTYPE_AP:
2229 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002230 pAdapter->device_mode = session_type;
2231
2232 status = hdd_init_ap_mode(pAdapter);
2233 if( VOS_STATUS_SUCCESS != status )
2234 goto err_free_netdev;
2235
2236 status = hdd_register_hostapd( pAdapter, rtnl_held );
2237 if( VOS_STATUS_SUCCESS != status )
2238 {
2239 hdd_deinit_adapter(pHddCtx, pAdapter);
2240 goto err_free_netdev;
2241 }
2242
2243 netif_tx_disable(pAdapter->dev);
2244 netif_carrier_off(pAdapter->dev);
2245
2246 hdd_set_conparam( 1 );
2247 break;
2248 }
2249 case WLAN_HDD_MONITOR:
2250 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002251 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2252 if( NULL == pAdapter )
2253 return NULL;
2254
2255 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
2256 pAdapter->device_mode = session_type;
2257 status = hdd_register_interface( pAdapter, rtnl_held );
2258#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
2259 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
2260#else
2261 pAdapter->dev->open = hdd_mon_open;
2262 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
2263#endif
2264 hdd_init_tx_rx( pAdapter );
2265 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2266 //Set adapter to be used for data tx. It will use either GO or softap.
2267 pAdapter->sessionCtx.monitor.pAdapterForTx =
2268 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
2269#ifdef WLAN_FEATURE_P2P
2270 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
2271 {
2272 pAdapter->sessionCtx.monitor.pAdapterForTx =
2273 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
2274 }
2275#endif
2276 /* This workqueue will be used to transmit management packet over
2277 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07002278 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
2279 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
2280 return NULL;
2281 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07002282
Jeff Johnson295189b2012-06-20 16:38:30 -07002283 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
2284 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07002285 }
2286 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002287 case WLAN_HDD_FTM:
2288 {
2289 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2290
2291 if( NULL == pAdapter )
2292 return NULL;
2293 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
2294 * message while loading driver in FTM mode. */
2295 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
2296 pAdapter->device_mode = session_type;
2297 status = hdd_register_interface( pAdapter, rtnl_held );
2298 }
2299 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002300 default:
2301 {
2302 VOS_ASSERT(0);
2303 return NULL;
2304 }
2305 }
2306
2307
2308 if( VOS_STATUS_SUCCESS == status )
2309 {
2310 //Add it to the hdd's session list.
2311 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
2312 if( NULL == pHddAdapterNode )
2313 {
2314 status = VOS_STATUS_E_NOMEM;
2315 }
2316 else
2317 {
2318 pHddAdapterNode->pAdapter = pAdapter;
2319 status = hdd_add_adapter_back ( pHddCtx,
2320 pHddAdapterNode );
2321 }
2322 }
2323
2324 if( VOS_STATUS_SUCCESS != status )
2325 {
2326 if( NULL != pAdapter )
2327 {
2328 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
2329 pAdapter = NULL;
2330 }
2331 if( NULL != pHddAdapterNode )
2332 {
2333 vos_mem_free( pHddAdapterNode );
2334 }
2335
2336 goto resume_bmps;
2337 }
2338
2339 if(VOS_STATUS_SUCCESS == status)
2340 {
2341 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
2342
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07002343 //Initialize the WoWL service
2344 if(!hdd_init_wowl(pAdapter))
2345 {
2346 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
2347 goto err_free_netdev;
2348 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002349 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002350 return pAdapter;
2351
2352err_free_netdev:
2353 free_netdev(pAdapter->dev);
2354 wlan_hdd_release_intf_addr( pHddCtx,
2355 pAdapter->macAddressCurrent.bytes );
2356
2357resume_bmps:
2358 //If bmps disabled enable it
2359 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
2360 {
2361 hdd_enable_bmps_imps(pHddCtx);
2362 }
2363 return NULL;
2364}
2365
2366VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
2367 tANI_U8 rtnl_held )
2368{
2369 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
2370 VOS_STATUS status;
2371
2372 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
2373 if( VOS_STATUS_SUCCESS != status )
2374 return status;
2375
2376 while ( pCurrent->pAdapter != pAdapter )
2377 {
2378 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
2379 if( VOS_STATUS_SUCCESS != status )
2380 break;
2381
2382 pCurrent = pNext;
2383 }
2384 pAdapterNode = pCurrent;
2385 if( VOS_STATUS_SUCCESS == status )
2386 {
2387 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2388 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
2389 hdd_remove_adapter( pHddCtx, pAdapterNode );
2390 vos_mem_free( pAdapterNode );
2391
Jeff Johnson295189b2012-06-20 16:38:30 -07002392
2393 /* If there is a single session of STA/P2P client, re-enable BMPS */
2394 if ((!vos_concurrent_sessions_running()) &&
2395 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
2396 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
2397 {
2398 hdd_enable_bmps_imps(pHddCtx);
2399 }
2400
2401 return VOS_STATUS_SUCCESS;
2402 }
2403
2404 return VOS_STATUS_E_FAILURE;
2405}
2406
2407VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
2408{
2409 hdd_adapter_list_node_t *pHddAdapterNode;
2410 VOS_STATUS status;
2411
2412 ENTER();
2413
2414 do
2415 {
2416 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
2417 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
2418 {
2419 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
2420 vos_mem_free( pHddAdapterNode );
2421 }
2422 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
2423
2424 EXIT();
2425
2426 return VOS_STATUS_SUCCESS;
2427}
2428
2429void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
2430{
2431 v_U8_t addIE[1] = {0};
2432
2433 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2434 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
2435 eANI_BOOLEAN_FALSE) )
2436 {
2437 hddLog(LOGE,
2438 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
2439 }
2440
2441 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2442 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
2443 eANI_BOOLEAN_FALSE) )
2444 {
2445 hddLog(LOGE,
2446 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
2447 }
2448
2449 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2450 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
2451 eANI_BOOLEAN_FALSE) )
2452 {
2453 hddLog(LOGE,
2454 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
2455 }
2456}
2457
2458VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2459{
2460 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2461 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2462 union iwreq_data wrqu;
2463
2464 ENTER();
2465
2466 switch(pAdapter->device_mode)
2467 {
2468 case WLAN_HDD_INFRA_STATION:
2469 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002470 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002471 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
2472 {
2473 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
2474 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
2475 pAdapter->sessionId,
2476 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
2477 else
2478 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
2479 pAdapter->sessionId,
2480 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2481 //success implies disconnect command got queued up successfully
2482 if(halStatus == eHAL_STATUS_SUCCESS)
2483 {
2484 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
2485 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2486 }
2487 memset(&wrqu, '\0', sizeof(wrqu));
2488 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2489 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2490 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2491 }
2492 else
2493 {
2494 hdd_abort_mac_scan(pHddCtx);
2495 }
2496
2497 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
2498 {
2499 INIT_COMPLETION(pAdapter->session_close_comp_var);
2500 if (eHAL_STATUS_SUCCESS ==
2501 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
2502 hdd_smeCloseSessionCallback, pAdapter))
2503 {
2504 //Block on a completion variable. Can't wait forever though.
2505 wait_for_completion_interruptible_timeout(
2506 &pAdapter->session_close_comp_var,
2507 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2508 }
2509 }
2510
2511 break;
2512
2513 case WLAN_HDD_SOFTAP:
2514 case WLAN_HDD_P2P_GO:
2515 //Any softap specific cleanup here...
2516 mutex_lock(&pHddCtx->sap_lock);
2517 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2518 {
2519 VOS_STATUS status;
2520 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2521
2522 //Stop Bss.
2523 status = WLANSAP_StopBss(pHddCtx->pvosContext);
2524 if (VOS_IS_STATUS_SUCCESS(status))
2525 {
2526 hdd_hostapd_state_t *pHostapdState =
2527 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2528
2529 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2530
2531 if (!VOS_IS_STATUS_SUCCESS(status))
2532 {
2533 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002534 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002535 }
2536 }
2537 else
2538 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002539 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002540 }
2541 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2542
2543 if (eHAL_STATUS_FAILURE ==
2544 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
2545 0, NULL, eANI_BOOLEAN_FALSE))
2546 {
2547 hddLog(LOGE,
2548 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002549 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002550 }
2551
2552 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2553 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2554 eANI_BOOLEAN_FALSE) )
2555 {
2556 hddLog(LOGE,
2557 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
2558 }
2559
2560 // Reset WNI_CFG_PROBE_RSP Flags
2561 wlan_hdd_reset_prob_rspies(pAdapter);
2562 kfree(pAdapter->sessionCtx.ap.beacon);
2563 pAdapter->sessionCtx.ap.beacon = NULL;
2564 }
2565 mutex_unlock(&pHddCtx->sap_lock);
2566 break;
2567 case WLAN_HDD_MONITOR:
2568 break;
2569 default:
2570 break;
2571 }
2572
2573 EXIT();
2574 return VOS_STATUS_SUCCESS;
2575}
2576
2577VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
2578{
2579 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2580 VOS_STATUS status;
2581 hdd_adapter_t *pAdapter;
2582
2583 ENTER();
2584
2585 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2586
2587 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2588 {
2589 pAdapter = pAdapterNode->pAdapter;
2590 netif_tx_disable(pAdapter->dev);
2591 netif_carrier_off(pAdapter->dev);
2592
2593 hdd_stop_adapter( pHddCtx, pAdapter );
2594
2595 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2596 pAdapterNode = pNext;
2597 }
2598
2599 EXIT();
2600
2601 return VOS_STATUS_SUCCESS;
2602}
2603
2604VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
2605{
2606 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2607 VOS_STATUS status;
2608 hdd_adapter_t *pAdapter;
2609
2610 ENTER();
2611
2612 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2613
2614 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2615 {
2616 pAdapter = pAdapterNode->pAdapter;
2617 netif_tx_disable(pAdapter->dev);
2618 netif_carrier_off(pAdapter->dev);
2619
2620 //Record whether STA is associated
2621 pAdapter->sessionCtx.station.bSendDisconnect =
2622 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
2623 VOS_TRUE : VOS_FALSE;
2624
2625 hdd_deinit_tx_rx(pAdapter);
2626 hdd_wmm_adapter_close(pAdapter);
2627
2628 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2629 pAdapterNode = pNext;
2630 }
2631
2632 EXIT();
2633
2634 return VOS_STATUS_SUCCESS;
2635}
2636
2637VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
2638{
2639 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2640 VOS_STATUS status;
2641 hdd_adapter_t *pAdapter;
2642 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
2643
2644 ENTER();
2645
2646 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2647
2648 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2649 {
2650 pAdapter = pAdapterNode->pAdapter;
2651
2652 switch(pAdapter->device_mode)
2653 {
2654 case WLAN_HDD_INFRA_STATION:
2655 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002656 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002657 hdd_init_station_mode(pAdapter);
2658 /* Open the gates for HDD to receive Wext commands */
2659 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002660 pHddCtx->scan_info.mScanPending = FALSE;
2661 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002662
2663 //Trigger the initial scan
2664 hdd_wlan_initial_scan(pAdapter);
2665
2666 //Indicate disconnect event to supplicant if associated previously
2667 if(pAdapter->sessionCtx.station.bSendDisconnect)
2668 {
2669 union iwreq_data wrqu;
2670 memset(&wrqu, '\0', sizeof(wrqu));
2671 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2672 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2673 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2674 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
2675
Jeff Johnson295189b2012-06-20 16:38:30 -07002676 /* indicate disconnected event to nl80211 */
2677 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
2678 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002679 }
2680 break;
2681
2682 case WLAN_HDD_SOFTAP:
2683 /* softAP can handle SSR */
2684 break;
2685
2686 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002687 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
2688 __func__);
2689 /* event supplicant to restart */
2690 cfg80211_del_sta(pAdapter->dev,
2691 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002692 break;
2693
2694 case WLAN_HDD_MONITOR:
2695 /* monitor interface start */
2696 break;
2697 default:
2698 break;
2699 }
2700
2701 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2702 pAdapterNode = pNext;
2703 }
2704
2705 EXIT();
2706
2707 return VOS_STATUS_SUCCESS;
2708}
2709
2710VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
2711{
2712 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2713 hdd_adapter_t *pAdapter;
2714 VOS_STATUS status;
2715 v_U32_t roamId;
2716
2717 ENTER();
2718
2719 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2720
2721 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2722 {
2723 pAdapter = pAdapterNode->pAdapter;
2724
2725 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
2726 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
2727 {
2728 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2729 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2730
2731 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2732 init_completion(&pAdapter->disconnect_comp_var);
2733 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
2734 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2735
2736 wait_for_completion_interruptible_timeout(
2737 &pAdapter->disconnect_comp_var,
2738 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2739
2740 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
2741 pHddCtx->isAmpAllowed = VOS_FALSE;
2742 sme_RoamConnect(pHddCtx->hHal,
2743 pAdapter->sessionId, &(pWextState->roamProfile),
2744 &roamId);
2745 }
2746
2747 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2748 pAdapterNode = pNext;
2749 }
2750
2751 EXIT();
2752
2753 return VOS_STATUS_SUCCESS;
2754}
2755
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002756bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07002757{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002758 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07002759}
2760
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002761/* Once SSR is disabled then it cannot be set. */
2762void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07002763{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002764 if (HDD_SSR_DISABLED == isSsrRequired)
2765 return;
2766
Jeff Johnson295189b2012-06-20 16:38:30 -07002767 isSsrRequired = value;
2768}
2769
2770VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
2771 hdd_adapter_list_node_t** ppAdapterNode)
2772{
2773 VOS_STATUS status;
2774 spin_lock(&pHddCtx->hddAdapters.lock);
2775 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
2776 (hdd_list_node_t**) ppAdapterNode );
2777 spin_unlock(&pHddCtx->hddAdapters.lock);
2778 return status;
2779}
2780
2781VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
2782 hdd_adapter_list_node_t* pAdapterNode,
2783 hdd_adapter_list_node_t** pNextAdapterNode)
2784{
2785 VOS_STATUS status;
2786 spin_lock(&pHddCtx->hddAdapters.lock);
2787 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
2788 (hdd_list_node_t*) pAdapterNode,
2789 (hdd_list_node_t**)pNextAdapterNode );
2790
2791 spin_unlock(&pHddCtx->hddAdapters.lock);
2792 return status;
2793}
2794
2795VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
2796 hdd_adapter_list_node_t* pAdapterNode)
2797{
2798 VOS_STATUS status;
2799 spin_lock(&pHddCtx->hddAdapters.lock);
2800 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
2801 &pAdapterNode->node );
2802 spin_unlock(&pHddCtx->hddAdapters.lock);
2803 return status;
2804}
2805
2806VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
2807 hdd_adapter_list_node_t** ppAdapterNode)
2808{
2809 VOS_STATUS status;
2810 spin_lock(&pHddCtx->hddAdapters.lock);
2811 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
2812 (hdd_list_node_t**) ppAdapterNode );
2813 spin_unlock(&pHddCtx->hddAdapters.lock);
2814 return status;
2815}
2816
2817VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
2818 hdd_adapter_list_node_t* pAdapterNode)
2819{
2820 VOS_STATUS status;
2821 spin_lock(&pHddCtx->hddAdapters.lock);
2822 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
2823 (hdd_list_node_t*) pAdapterNode );
2824 spin_unlock(&pHddCtx->hddAdapters.lock);
2825 return status;
2826}
2827
2828VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
2829 hdd_adapter_list_node_t* pAdapterNode)
2830{
2831 VOS_STATUS status;
2832 spin_lock(&pHddCtx->hddAdapters.lock);
2833 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
2834 (hdd_list_node_t*) pAdapterNode );
2835 spin_unlock(&pHddCtx->hddAdapters.lock);
2836 return status;
2837}
2838
2839hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
2840 tSirMacAddr macAddr )
2841{
2842 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2843 hdd_adapter_t *pAdapter;
2844 VOS_STATUS status;
2845
2846 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2847
2848 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2849 {
2850 pAdapter = pAdapterNode->pAdapter;
2851
2852 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
2853 macAddr, sizeof(tSirMacAddr) ) )
2854 {
2855 return pAdapter;
2856 }
2857 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2858 pAdapterNode = pNext;
2859 }
2860
2861 return NULL;
2862
2863}
2864
2865hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
2866{
2867 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2868 hdd_adapter_t *pAdapter;
2869 VOS_STATUS status;
2870
2871 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2872
2873 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2874 {
2875 pAdapter = pAdapterNode->pAdapter;
2876
2877 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
2878 IFNAMSIZ ) )
2879 {
2880 return pAdapter;
2881 }
2882 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2883 pAdapterNode = pNext;
2884 }
2885
2886 return NULL;
2887
2888}
2889
2890hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
2891{
2892 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2893 hdd_adapter_t *pAdapter;
2894 VOS_STATUS status;
2895
2896 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2897
2898 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2899 {
2900 pAdapter = pAdapterNode->pAdapter;
2901
2902 if( pAdapter && (mode == pAdapter->device_mode) )
2903 {
2904 return pAdapter;
2905 }
2906 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2907 pAdapterNode = pNext;
2908 }
2909
2910 return NULL;
2911
2912}
2913
2914//Remove this function later
2915hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
2916{
2917 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2918 hdd_adapter_t *pAdapter;
2919 VOS_STATUS status;
2920
2921 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2922
2923 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2924 {
2925 pAdapter = pAdapterNode->pAdapter;
2926
2927 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
2928 {
2929 return pAdapter;
2930 }
2931
2932 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2933 pAdapterNode = pNext;
2934 }
2935
2936 return NULL;
2937
2938}
2939
Jeff Johnson295189b2012-06-20 16:38:30 -07002940/**---------------------------------------------------------------------------
2941
2942 \brief hdd_set_monitor_tx_adapter() -
2943
2944 This API initializes the adapter to be used while transmitting on monitor
2945 adapter.
2946
2947 \param - pHddCtx - Pointer to the HDD context.
2948 pAdapter - Adapter that will used for TX. This can be NULL.
2949 \return - None.
2950 --------------------------------------------------------------------------*/
2951void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2952{
2953 hdd_adapter_t *pMonAdapter;
2954
2955 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
2956
2957 if( NULL != pMonAdapter )
2958 {
2959 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
2960 }
2961}
Jeff Johnson295189b2012-06-20 16:38:30 -07002962/**---------------------------------------------------------------------------
2963
2964 \brief hdd_select_queue() -
2965
2966 This API returns the operating channel of the requested device mode
2967
2968 \param - pHddCtx - Pointer to the HDD context.
2969 - mode - Device mode for which operating channel is required
2970 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
2971 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
2972 \return - channel number. "0" id the requested device is not found OR it is not connected.
2973 --------------------------------------------------------------------------*/
2974v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
2975{
2976 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2977 VOS_STATUS status;
2978 hdd_adapter_t *pAdapter;
2979 v_U8_t operatingChannel = 0;
2980
2981 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2982
2983 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2984 {
2985 pAdapter = pAdapterNode->pAdapter;
2986
2987 if( mode == pAdapter->device_mode )
2988 {
2989 switch(pAdapter->device_mode)
2990 {
2991 case WLAN_HDD_INFRA_STATION:
2992 case WLAN_HDD_P2P_CLIENT:
2993 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
2994 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
2995 break;
2996 case WLAN_HDD_SOFTAP:
2997 case WLAN_HDD_P2P_GO:
2998 /*softap connection info */
2999 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3000 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
3001 break;
3002 default:
3003 break;
3004 }
3005
3006 break; //Found the device of interest. break the loop
3007 }
3008
3009 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3010 pAdapterNode = pNext;
3011 }
3012 return operatingChannel;
3013}
3014
3015#ifdef WLAN_FEATURE_PACKET_FILTERING
3016/**---------------------------------------------------------------------------
3017
3018 \brief hdd_set_multicast_list() -
3019
3020 This used to set the multicast address list.
3021
3022 \param - dev - Pointer to the WLAN device.
3023 - skb - Pointer to OS packet (sk_buff).
3024 \return - success/fail
3025
3026 --------------------------------------------------------------------------*/
3027static void hdd_set_multicast_list(struct net_device *dev)
3028{
3029 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07003030 int mc_count;
3031 int i = 0;
3032 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303033
3034 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07003035 {
3036 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303037 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003038 return;
3039 }
3040
3041 if (dev->flags & IFF_ALLMULTI)
3042 {
3043 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003044 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303045 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003046 }
3047 else
3048 {
3049 mc_count = netdev_mc_count(dev);
3050 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003051 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07003052 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
3053 {
3054 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003055 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303056 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003057 return;
3058 }
3059
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303060 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07003061
3062 netdev_for_each_mc_addr(ha, dev) {
3063 if (i == mc_count)
3064 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303065 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
3066 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
3067 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003068 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303069 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07003070 i++;
3071 }
3072 }
3073 return;
3074}
3075#endif
3076
3077/**---------------------------------------------------------------------------
3078
3079 \brief hdd_select_queue() -
3080
3081 This function is registered with the Linux OS for network
3082 core to decide which queue to use first.
3083
3084 \param - dev - Pointer to the WLAN device.
3085 - skb - Pointer to OS packet (sk_buff).
3086 \return - ac, Queue Index/access category corresponding to UP in IP header
3087
3088 --------------------------------------------------------------------------*/
3089v_U16_t hdd_select_queue(struct net_device *dev,
3090 struct sk_buff *skb)
3091{
3092 return hdd_wmm_select_queue(dev, skb);
3093}
3094
3095
3096/**---------------------------------------------------------------------------
3097
3098 \brief hdd_wlan_initial_scan() -
3099
3100 This function triggers the initial scan
3101
3102 \param - pAdapter - Pointer to the HDD adapter.
3103
3104 --------------------------------------------------------------------------*/
3105void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
3106{
3107 tCsrScanRequest scanReq;
3108 tCsrChannelInfo channelInfo;
3109 eHalStatus halStatus;
3110 unsigned long scanId;
3111 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3112
3113 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
3114 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
3115 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
3116
3117 if(sme_Is11dSupported(pHddCtx->hHal))
3118 {
3119 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
3120 if ( HAL_STATUS_SUCCESS( halStatus ) )
3121 {
3122 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
3123 if( !scanReq.ChannelInfo.ChannelList )
3124 {
3125 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
3126 vos_mem_free(channelInfo.ChannelList);
3127 return;
3128 }
3129 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
3130 channelInfo.numOfChannels);
3131 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
3132 vos_mem_free(channelInfo.ChannelList);
3133 }
3134
3135 scanReq.scanType = eSIR_PASSIVE_SCAN;
3136 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
3137 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
3138 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
3139 }
3140 else
3141 {
3142 scanReq.scanType = eSIR_ACTIVE_SCAN;
3143 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
3144 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
3145 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
3146 }
3147
3148 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
3149 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3150 {
3151 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
3152 __func__, halStatus );
3153 }
3154
3155 if(sme_Is11dSupported(pHddCtx->hHal))
3156 vos_mem_free(scanReq.ChannelInfo.ChannelList);
3157}
3158
3159struct fullPowerContext
3160{
3161 struct completion completion;
3162 unsigned int magic;
3163};
3164#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
3165
3166/**---------------------------------------------------------------------------
3167
3168 \brief hdd_full_power_callback() - HDD full power callback function
3169
3170 This is the function invoked by SME to inform the result of a full power
3171 request issued by HDD
3172
3173 \param - callbackcontext - Pointer to cookie
3174 \param - status - result of request
3175
3176 \return - None
3177
3178 --------------------------------------------------------------------------*/
3179static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
3180{
3181 struct fullPowerContext *pContext = callbackContext;
3182
3183 hddLog(VOS_TRACE_LEVEL_INFO,
3184 "%s: context = %p, status = %d", pContext, status);
3185
3186 if (NULL == callbackContext)
3187 {
3188 hddLog(VOS_TRACE_LEVEL_ERROR,
3189 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003190 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07003191 return;
3192 }
3193
3194 /* there is a race condition that exists between this callback function
3195 and the caller since the caller could time out either before or
3196 while this code is executing. we'll assume the timeout hasn't
3197 occurred, but we'll verify that right before we save our work */
3198
3199 if (POWER_CONTEXT_MAGIC != pContext->magic)
3200 {
3201 /* the caller presumably timed out so there is nothing we can do */
3202 hddLog(VOS_TRACE_LEVEL_WARN,
3203 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003204 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07003205 return;
3206 }
3207
3208 /* the race is on. caller could have timed out immediately after
3209 we verified the magic, but if so, caller will wait a short time
3210 for us to notify the caller, so the context will stay valid */
3211 complete(&pContext->completion);
3212}
3213
3214/**---------------------------------------------------------------------------
3215
3216 \brief hdd_wlan_exit() - HDD WLAN exit function
3217
3218 This is the driver exit point (invoked during rmmod)
3219
3220 \param - pHddCtx - Pointer to the HDD Context
3221
3222 \return - None
3223
3224 --------------------------------------------------------------------------*/
3225void hdd_wlan_exit(hdd_context_t *pHddCtx)
3226{
3227 eHalStatus halStatus;
3228 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
3229 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05303230 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003231 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003232 struct fullPowerContext powerContext;
3233 long lrc;
3234
3235 ENTER();
3236
Jeff Johnson88ba7742013-02-27 14:36:02 -08003237 if (VOS_FTM_MODE != hdd_get_conparam())
3238 {
3239 // Unloading, restart logic is no more required.
3240 wlan_hdd_restart_deinit(pHddCtx);
3241 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003242
Jeff Johnson295189b2012-06-20 16:38:30 -07003243 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003244 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003245 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003246 {
3247 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
3248 WLAN_HDD_INFRA_STATION);
3249 if (pAdapter == NULL)
3250 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3251
3252 if (pAdapter != NULL)
3253 {
3254 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
3255 hdd_UnregisterWext(pAdapter->dev);
3256 }
3257 }
3258 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003259
Jeff Johnson295189b2012-06-20 16:38:30 -07003260 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08003261 {
3262 wlan_hdd_ftm_close(pHddCtx);
3263 goto free_hdd_ctx;
3264 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003265 //Stop the Interface TX queue.
3266 //netif_tx_disable(pWlanDev);
3267 //netif_carrier_off(pWlanDev);
3268
Jeff Johnson295189b2012-06-20 16:38:30 -07003269 if (VOS_STA_SAP_MODE == hdd_get_conparam())
3270 {
3271 pAdapter = hdd_get_adapter(pHddCtx,
3272 WLAN_HDD_SOFTAP);
3273 }
3274 else
3275 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003276 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003277 {
3278 pAdapter = hdd_get_adapter(pHddCtx,
3279 WLAN_HDD_INFRA_STATION);
3280 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003281 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003282 /* DeRegister with platform driver as client for Suspend/Resume */
3283 vosStatus = hddDeregisterPmOps(pHddCtx);
3284 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3285 {
3286 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
3287 VOS_ASSERT(0);
3288 }
3289
3290 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
3291 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3292 {
3293 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
3294 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003295
Chilam NG571c65a2013-01-19 12:27:36 +05303296#ifdef FEATURE_WLAN_TDLS
3297 wlan_hdd_tdls_exit();
3298#endif
3299
Jeff Johnson295189b2012-06-20 16:38:30 -07003300 // Cancel any outstanding scan requests. We are about to close all
3301 // of our adapters, but an adapter structure is what SME passes back
3302 // to our callback function. Hence if there are any outstanding scan
3303 // requests then there is a race condition between when the adapter
3304 // is closed and when the callback is invoked. We try to resolve that
3305 // race condition here by canceling any outstanding scans before we
3306 // close the adapters.
3307 // Note that the scans may be cancelled in an asynchronous manner, so
3308 // ideally there needs to be some kind of synchronization. Rather than
3309 // introduce a new synchronization here, we will utilize the fact that
3310 // we are about to Request Full Power, and since that is synchronized,
3311 // the expectation is that by the time Request Full Power has completed,
3312 // all scans will be cancelled.
3313 hdd_abort_mac_scan( pHddCtx );
3314
3315 //Disable IMPS/BMPS as we do not want the device to enter any power
3316 //save mode during shutdown
3317 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3318 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3319 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
3320
3321 //Ensure that device is in full power as we will touch H/W during vos_Stop
3322 init_completion(&powerContext.completion);
3323 powerContext.magic = POWER_CONTEXT_MAGIC;
3324
3325 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
3326 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
3327
3328 if (eHAL_STATUS_SUCCESS != halStatus)
3329 {
3330 if (eHAL_STATUS_PMC_PENDING == halStatus)
3331 {
3332 /* request was sent -- wait for the response */
3333 lrc = wait_for_completion_interruptible_timeout(
3334 &powerContext.completion,
3335 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
3336 /* either we have a response or we timed out
3337 either way, first invalidate our magic */
3338 powerContext.magic = 0;
3339 if (lrc <= 0)
3340 {
3341 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003342 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07003343 /* there is a race condition such that the callback
3344 function could be executing at the same time we are. of
3345 primary concern is if the callback function had already
3346 verified the "magic" but hasn't yet set the completion
3347 variable. Since the completion variable is on our
3348 stack, we'll delay just a bit to make sure the data is
3349 still valid if that is the case */
3350 msleep(50);
3351 }
3352 }
3353 else
3354 {
3355 hddLog(VOS_TRACE_LEVEL_ERROR,
3356 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003357 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07003358 VOS_ASSERT(0);
3359 /* continue -- need to clean up as much as possible */
3360 }
3361 }
3362
3363 // Unregister the Net Device Notifier
3364 unregister_netdevice_notifier(&hdd_netdev_notifier);
3365
Jeff Johnson295189b2012-06-20 16:38:30 -07003366 hdd_stop_all_adapters( pHddCtx );
3367
Jeff Johnson295189b2012-06-20 16:38:30 -07003368#ifdef WLAN_BTAMP_FEATURE
3369 vosStatus = WLANBAP_Stop(pVosContext);
3370 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3371 {
3372 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3373 "%s: Failed to stop BAP",__func__);
3374 }
3375#endif //WLAN_BTAMP_FEATURE
3376
3377 //Stop all the modules
3378 vosStatus = vos_stop( pVosContext );
3379 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3380 {
3381 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3382 "%s: Failed to stop VOSS",__func__);
3383 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3384 }
3385
Jeff Johnson295189b2012-06-20 16:38:30 -07003386 //Assert Deep sleep signal now to put Libra HW in lowest power state
3387 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
3388 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3389
3390 //Vote off any PMIC voltage supplies
3391 vos_chipPowerDown(NULL, NULL, NULL);
3392
3393 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
3394
3395 //Clean up HDD Nlink Service
3396 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
3397 nl_srv_exit();
3398
3399 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07003400 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003401
3402 //Close the scheduler before calling vos_close to make sure no thread is
3403 // scheduled after the each module close is called i.e after all the data
3404 // structures are freed.
3405 vosStatus = vos_sched_close( pVosContext );
3406 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
3407 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
3408 "%s: Failed to close VOSS Scheduler",__func__);
3409 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3410 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003411#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07003412#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3413 /* Destroy the wake lock */
3414 wake_lock_destroy(&pHddCtx->rx_wake_lock);
3415#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08003416 /* Destroy the wake lock */
3417 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003418#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003419
3420 //Close VOSS
3421 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
3422 vos_close(pVosContext);
3423
Jeff Johnson295189b2012-06-20 16:38:30 -07003424 //Close Watchdog
3425 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3426 vos_watchdog_close(pVosContext);
3427
3428 /* Cancel the vote for XO Core ON.
3429 * This is done here to ensure there is no race condition since MC, TX and WD threads have
3430 * exited at this point
3431 */
3432 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
3433 " when WLAN is turned OFF\n");
3434 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
3435 {
3436 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
3437 " Not returning failure."
3438 " Power consumed will be high\n");
3439 }
3440
3441 hdd_close_all_adapters( pHddCtx );
3442
3443
3444 //Free up dynamically allocated members inside HDD Adapter
3445 kfree(pHddCtx->cfg_ini);
3446 pHddCtx->cfg_ini= NULL;
3447
3448 /* free the power on lock from platform driver */
3449 if (free_riva_power_on_lock("wlan"))
3450 {
3451 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
3452 __func__);
3453 }
3454
Jeff Johnson88ba7742013-02-27 14:36:02 -08003455free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08003456 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07003457 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07003458 if (hdd_is_ssr_required())
3459 {
3460 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07003461 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07003462 msleep(5000);
3463 }
3464 hdd_set_ssr_required (VOS_FALSE);
3465}
3466
3467
3468/**---------------------------------------------------------------------------
3469
3470 \brief hdd_update_config_from_nv() - Function to update the contents of
3471 the running configuration with parameters taken from NV storage
3472
3473 \param - pHddCtx - Pointer to the HDD global context
3474
3475 \return - VOS_STATUS_SUCCESS if successful
3476
3477 --------------------------------------------------------------------------*/
3478static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
3479{
Jeff Johnson295189b2012-06-20 16:38:30 -07003480 v_BOOL_t itemIsValid = VOS_FALSE;
3481 VOS_STATUS status;
3482 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
3483 v_U8_t macLoop;
3484
3485 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
3486 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
3487 if(status != VOS_STATUS_SUCCESS)
3488 {
3489 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
3490 return VOS_STATUS_E_FAILURE;
3491 }
3492
3493 if (itemIsValid == VOS_TRUE)
3494 {
3495 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
3496 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
3497 VOS_MAX_CONCURRENCY_PERSONA);
3498 if(status != VOS_STATUS_SUCCESS)
3499 {
3500 /* Get MAC from NV fail, not update CFG info
3501 * INI MAC value will be used for MAC setting */
3502 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
3503 return VOS_STATUS_E_FAILURE;
3504 }
3505
3506 /* If first MAC is not valid, treat all others are not valid
3507 * Then all MACs will be got from ini file */
3508 if(vos_is_macaddr_zero(&macFromNV[0]))
3509 {
3510 /* MAC address in NV file is not configured yet */
3511 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
3512 return VOS_STATUS_E_INVAL;
3513 }
3514
3515 /* Get MAC address from NV, update CFG info */
3516 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
3517 {
3518 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
3519 {
3520 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
3521 /* This MAC is not valid, skip it
3522 * This MAC will be got from ini file */
3523 }
3524 else
3525 {
3526 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
3527 (v_U8_t *)&macFromNV[macLoop].bytes[0],
3528 VOS_MAC_ADDR_SIZE);
3529 }
3530 }
3531 }
3532 else
3533 {
3534 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
3535 return VOS_STATUS_E_FAILURE;
3536 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003537
Jeff Johnson295189b2012-06-20 16:38:30 -07003538
3539 return VOS_STATUS_SUCCESS;
3540}
3541
3542/**---------------------------------------------------------------------------
3543
3544 \brief hdd_post_voss_start_config() - HDD post voss start config helper
3545
3546 \param - pAdapter - Pointer to the HDD
3547
3548 \return - None
3549
3550 --------------------------------------------------------------------------*/
3551VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
3552{
3553 eHalStatus halStatus;
3554 v_U32_t listenInterval;
3555
Jeff Johnson295189b2012-06-20 16:38:30 -07003556
3557 // Send ready indication to the HDD. This will kick off the MAC
3558 // into a 'running' state and should kick off an initial scan.
3559 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
3560 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3561 {
3562 hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
3563 "code %08d [x%08x]",__func__, halStatus, halStatus );
3564 return VOS_STATUS_E_FAILURE;
3565 }
3566
3567 // Set default LI into HDD context,
3568 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
3569 // And RIVA will crash
3570 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
3571 pHddCtx->hdd_actual_LI_value = listenInterval;
3572
3573 return VOS_STATUS_SUCCESS;
3574}
3575
Jeff Johnson295189b2012-06-20 16:38:30 -07003576/* wake lock APIs for HDD */
3577void hdd_prevent_suspend(void)
3578{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003579#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003580 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003581#else
3582 wcnss_prevent_suspend();
3583#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003584}
3585
3586void hdd_allow_suspend(void)
3587{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003588#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003589 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003590#else
3591 wcnss_allow_suspend();
3592#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003593}
3594
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003595void hdd_allow_suspend_timeout(v_U32_t timeout)
3596{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003597#ifdef WLAN_OPEN_SOURCE
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003598 wake_lock_timeout(&wlan_wake_lock, timeout);
3599#else
3600 /* Do nothing as there is no API in wcnss for timeout*/
3601#endif
3602}
3603
Jeff Johnson295189b2012-06-20 16:38:30 -07003604/**---------------------------------------------------------------------------
3605
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003606 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
3607 information between Host and Riva
3608
3609 This function gets reported version of FW
3610 It also finds the version of Riva headers used to compile the host
3611 It compares the above two and prints a warning if they are different
3612 It gets the SW and HW version string
3613 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
3614 indicating the features they support through a bitmap
3615
3616 \param - pHddCtx - Pointer to HDD context
3617
3618 \return - void
3619
3620 --------------------------------------------------------------------------*/
3621
3622void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
3623{
3624
3625 tSirVersionType versionCompiled;
3626 tSirVersionType versionReported;
3627 tSirVersionString versionString;
3628 tANI_U8 fwFeatCapsMsgSupported = 0;
3629 VOS_STATUS vstatus;
3630
3631 /* retrieve and display WCNSS version information */
3632 do {
3633
3634 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
3635 &versionCompiled);
3636 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3637 {
3638 hddLog(VOS_TRACE_LEVEL_FATAL,
3639 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003640 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003641 break;
3642 }
3643
3644 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
3645 &versionReported);
3646 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3647 {
3648 hddLog(VOS_TRACE_LEVEL_FATAL,
3649 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003650 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003651 break;
3652 }
3653
3654 if ((versionCompiled.major != versionReported.major) ||
3655 (versionCompiled.minor != versionReported.minor) ||
3656 (versionCompiled.version != versionReported.version) ||
3657 (versionCompiled.revision != versionReported.revision))
3658 {
3659 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
3660 "Host expected %u.%u.%u.%u\n",
3661 WLAN_MODULE_NAME,
3662 (int)versionReported.major,
3663 (int)versionReported.minor,
3664 (int)versionReported.version,
3665 (int)versionReported.revision,
3666 (int)versionCompiled.major,
3667 (int)versionCompiled.minor,
3668 (int)versionCompiled.version,
3669 (int)versionCompiled.revision);
3670 }
3671 else
3672 {
3673 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
3674 WLAN_MODULE_NAME,
3675 (int)versionReported.major,
3676 (int)versionReported.minor,
3677 (int)versionReported.version,
3678 (int)versionReported.revision);
3679 }
3680
3681 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
3682 versionString,
3683 sizeof(versionString));
3684 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3685 {
3686 hddLog(VOS_TRACE_LEVEL_FATAL,
3687 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003688 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003689 break;
3690 }
3691
3692 pr_info("%s: WCNSS software version %s\n",
3693 WLAN_MODULE_NAME, versionString);
3694
3695 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
3696 versionString,
3697 sizeof(versionString));
3698 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3699 {
3700 hddLog(VOS_TRACE_LEVEL_FATAL,
3701 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003702 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003703 break;
3704 }
3705
3706 pr_info("%s: WCNSS hardware version %s\n",
3707 WLAN_MODULE_NAME, versionString);
3708
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003709 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
3710 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003711 send the message only if it the riva is 1.1
3712 minor numbers for different riva branches:
3713 0 -> (1.0)Mainline Build
3714 1 -> (1.1)Mainline Build
3715 2->(1.04) Stability Build
3716 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003717 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003718 ((versionReported.minor>=1) && (versionReported.version>=1)))
3719 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
3720 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003721
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003722 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08003723 {
3724#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
3725 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
3726 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
3727#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003728 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08003729 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003730
3731 } while (0);
3732
3733}
3734
3735/**---------------------------------------------------------------------------
3736
Jeff Johnson295189b2012-06-20 16:38:30 -07003737 \brief hdd_wlan_startup() - HDD init function
3738
3739 This is the driver startup code executed once a WLAN device has been detected
3740
3741 \param - dev - Pointer to the underlying device
3742
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003743 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07003744
3745 --------------------------------------------------------------------------*/
3746
3747int hdd_wlan_startup(struct device *dev )
3748{
3749 VOS_STATUS status;
3750 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003751 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003752 hdd_context_t *pHddCtx = NULL;
3753 v_CONTEXT_t pVosContext= NULL;
3754#ifdef WLAN_BTAMP_FEATURE
3755 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
3756 WLANBAP_ConfigType btAmpConfig;
3757 hdd_config_t *pConfig;
3758#endif
3759 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07003760 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003761
3762 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07003763 /*
3764 * cfg80211: wiphy allocation
3765 */
3766 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
3767
3768 if(wiphy == NULL)
3769 {
3770 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003771 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003772 }
3773
3774 pHddCtx = wiphy_priv(wiphy);
3775
Jeff Johnson295189b2012-06-20 16:38:30 -07003776 //Initialize the adapter context to zeros.
3777 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
3778
Jeff Johnson295189b2012-06-20 16:38:30 -07003779 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003780 hdd_prevent_suspend();
3781 pHddCtx->isLoadUnloadInProgress = TRUE;
3782
3783 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
3784
3785 /*Get vos context here bcoz vos_open requires it*/
3786 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
3787
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08003788 if(pVosContext == NULL)
3789 {
3790 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
3791 goto err_free_hdd_context;
3792 }
3793
Jeff Johnson295189b2012-06-20 16:38:30 -07003794 //Save the Global VOSS context in adapter context for future.
3795 pHddCtx->pvosContext = pVosContext;
3796
3797 //Save the adapter context in global context for future.
3798 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
3799
Jeff Johnson295189b2012-06-20 16:38:30 -07003800 pHddCtx->parent_dev = dev;
3801
3802 init_completion(&pHddCtx->full_pwr_comp_var);
3803 init_completion(&pHddCtx->standby_comp_var);
3804 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003805 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003806 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003807
3808 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
3809
3810 // Load all config first as TL config is needed during vos_open
3811 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
3812 if(pHddCtx->cfg_ini == NULL)
3813 {
3814 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
3815 goto err_free_hdd_context;
3816 }
3817
3818 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
3819
3820 // Read and parse the qcom_cfg.ini file
3821 status = hdd_parse_config_ini( pHddCtx );
3822 if ( VOS_STATUS_SUCCESS != status )
3823 {
3824 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
3825 __func__, WLAN_INI_FILE);
3826 goto err_config;
3827 }
3828
Jeff Johnson295189b2012-06-20 16:38:30 -07003829 /*
3830 * cfg80211: Initialization and registration ...
3831 */
3832 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
3833 {
3834 hddLog(VOS_TRACE_LEVEL_FATAL,
3835 "%s: wlan_hdd_cfg80211_register return failure", __func__);
3836 goto err_wiphy_reg;
3837 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003838
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003839 // Update VOS trace levels based upon the cfg.ini
3840 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
3841 pHddCtx->cfg_ini->vosTraceEnableBAP);
3842 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
3843 pHddCtx->cfg_ini->vosTraceEnableTL);
3844 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
3845 pHddCtx->cfg_ini->vosTraceEnableWDI);
3846 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
3847 pHddCtx->cfg_ini->vosTraceEnableHDD);
3848 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
3849 pHddCtx->cfg_ini->vosTraceEnableSME);
3850 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
3851 pHddCtx->cfg_ini->vosTraceEnablePE);
3852 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
3853 pHddCtx->cfg_ini->vosTraceEnableWDA);
3854 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
3855 pHddCtx->cfg_ini->vosTraceEnableSYS);
3856 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
3857 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003858 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
3859 pHddCtx->cfg_ini->vosTraceEnableSAP);
3860 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
3861 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003862
Jeff Johnson295189b2012-06-20 16:38:30 -07003863 // Update WDI trace levels based upon the cfg.ini
3864 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
3865 pHddCtx->cfg_ini->wdiTraceEnableDAL);
3866 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
3867 pHddCtx->cfg_ini->wdiTraceEnableCTL);
3868 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
3869 pHddCtx->cfg_ini->wdiTraceEnableDAT);
3870 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
3871 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003872
Jeff Johnson88ba7742013-02-27 14:36:02 -08003873 if (VOS_FTM_MODE == hdd_get_conparam())
3874 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003875 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
3876 {
3877 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
3878 goto err_free_hdd_context;
3879 }
3880 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
3881 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08003882 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003883
Jeff Johnson88ba7742013-02-27 14:36:02 -08003884 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07003885 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3886 {
3887 status = vos_watchdog_open(pVosContext,
3888 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
3889
3890 if(!VOS_IS_STATUS_SUCCESS( status ))
3891 {
3892 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003893 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07003894 }
3895 }
3896
3897 pHddCtx->isLogpInProgress = FALSE;
3898 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
3899
Jeff Johnson295189b2012-06-20 16:38:30 -07003900 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
3901 if(!VOS_IS_STATUS_SUCCESS(status))
3902 {
3903 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003904 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07003905 }
3906
Jeff Johnson295189b2012-06-20 16:38:30 -07003907 status = vos_open( &pVosContext, 0);
3908 if ( !VOS_IS_STATUS_SUCCESS( status ))
3909 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003910 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
3911 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07003912 }
3913
Jeff Johnson295189b2012-06-20 16:38:30 -07003914 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
3915
3916 if ( NULL == pHddCtx->hHal )
3917 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003918 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003919 goto err_vosclose;
3920 }
3921
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003922 status = vos_preStart( pHddCtx->pvosContext );
3923 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3924 {
3925 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
3926 goto err_vosclose;
3927 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003928
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003929 /* Note that the vos_preStart() sequence triggers the cfg download.
3930 The cfg download must occur before we update the SME config
3931 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07003932 status = hdd_set_sme_config( pHddCtx );
3933
3934 if ( VOS_STATUS_SUCCESS != status )
3935 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003936 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
3937 goto err_vosclose;
3938 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003939
3940 //Initialize the WMM module
3941 status = hdd_wmm_init(pHddCtx);
3942 if (!VOS_IS_STATUS_SUCCESS(status))
3943 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003944 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003945 goto err_vosclose;
3946 }
3947
Jeff Johnson295189b2012-06-20 16:38:30 -07003948 /* In the integrated architecture we update the configuration from
3949 the INI file and from NV before vOSS has been started so that
3950 the final contents are available to send down to the cCPU */
3951
3952 // Apply the cfg.ini to cfg.dat
3953 if (FALSE == hdd_update_config_dat(pHddCtx))
3954 {
3955 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
3956 goto err_vosclose;
3957 }
3958
3959 // Apply the NV to cfg.dat
3960 /* Prima Update MAC address only at here */
3961 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
3962 {
3963#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
3964 /* There was not a valid set of MAC Addresses in NV. See if the
3965 default addresses were modified by the cfg.ini settings. If so,
3966 we'll use them, but if not, we'll autogenerate a set of MAC
3967 addresses based upon the device serial number */
3968
3969 static const v_MACADDR_t default_address =
3970 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
3971 unsigned int serialno;
3972 int i;
3973
3974 serialno = wcnss_get_serial_number();
3975 if ((0 != serialno) &&
3976 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
3977 sizeof(default_address))))
3978 {
3979 /* cfg.ini has the default address, invoke autogen logic */
3980
3981 /* MAC address has 3 bytes of OUI so we have a maximum of 3
3982 bytes of the serial number that can be used to generate
3983 the other 3 bytes of the MAC address. Mask off all but
3984 the lower 3 bytes (this will also make sure we don't
3985 overflow in the next step) */
3986 serialno &= 0x00FFFFFF;
3987
3988 /* we need a unique address for each session */
3989 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
3990
3991 /* autogen all addresses */
3992 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3993 {
3994 /* start with the entire default address */
3995 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
3996 /* then replace the lower 3 bytes */
3997 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
3998 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
3999 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
4000
4001 serialno++;
4002 }
4003
4004 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
4005 MAC_ADDRESS_STR,
4006 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4007 }
4008 else
4009#endif //WLAN_AUTOGEN_MACADDR_FEATURE
4010 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004011 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004012 "%s: Invalid MAC address in NV, using MAC from ini file "
4013 MAC_ADDRESS_STR, __func__,
4014 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4015 }
4016 }
4017 {
4018 eHalStatus halStatus;
4019 // Set the MAC Address
4020 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
4021 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
4022 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
4023 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
4024
4025 if (!HAL_STATUS_SUCCESS( halStatus ))
4026 {
4027 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
4028 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08004029 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004030 }
4031 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004032
4033 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
4034 Note: Firmware image will be read and downloaded inside vos_start API */
4035 status = vos_start( pHddCtx->pvosContext );
4036 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4037 {
4038 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
4039 goto err_vosclose;
4040 }
4041
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004042 /* Exchange capability info between Host and FW and also get versioning info from FW */
4043 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004044
4045 status = hdd_post_voss_start_config( pHddCtx );
4046 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4047 {
4048 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
4049 __func__);
4050 goto err_vosstop;
4051 }
4052
Jeff Johnson295189b2012-06-20 16:38:30 -07004053 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4054 {
4055 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
4056 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4057 }
4058 else
4059 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004060 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
4061 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4062 if (pAdapter != NULL)
4063 {
4064#ifdef WLAN_FEATURE_P2P
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304065 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07004066 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304067 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
4068 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
4069 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07004070
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304071 /* Generate the P2P Device Address. This consists of the device's
4072 * primary MAC address with the locally administered bit set.
4073 */
4074 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07004075 }
4076 else
4077 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304078 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
4079 if (p2p_dev_addr != NULL)
4080 {
4081 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
4082 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
4083 }
4084 else
4085 {
4086 hddLog(VOS_TRACE_LEVEL_FATAL,
4087 "%s: Failed to allocate mac_address for p2p_device",
4088 __func__);
4089 goto err_close_adapter;
4090 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004091 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004092
4093 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
4094 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
4095 if ( NULL == pP2pAdapter )
4096 {
4097 hddLog(VOS_TRACE_LEVEL_FATAL,
4098 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004099 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004100 goto err_close_adapter;
4101 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004102#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004103 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004104 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004105
4106 if( pAdapter == NULL )
4107 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004108 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
4109 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004110 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004111
Jeff Johnson295189b2012-06-20 16:38:30 -07004112#ifdef WLAN_BTAMP_FEATURE
4113 vStatus = WLANBAP_Open(pVosContext);
4114 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4115 {
4116 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4117 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004118 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004119 }
4120
4121 vStatus = BSL_Init(pVosContext);
4122 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4123 {
4124 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4125 "%s: Failed to Init BSL",__func__);
4126 goto err_bap_close;
4127 }
4128 vStatus = WLANBAP_Start(pVosContext);
4129 if (!VOS_IS_STATUS_SUCCESS(vStatus))
4130 {
4131 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4132 "%s: Failed to start TL",__func__);
4133 goto err_bap_close;
4134 }
4135
4136 pConfig = pHddCtx->cfg_ini;
4137 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
4138 status = WLANBAP_SetConfig(&btAmpConfig);
4139
4140#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07004141
Jeff Johnson295189b2012-06-20 16:38:30 -07004142#ifdef FEATURE_WLAN_SCAN_PNO
4143 /*SME must send channel update configuration to RIVA*/
4144 sme_UpdateChannelConfig(pHddCtx->hHal);
4145#endif
4146
Jeff Johnson295189b2012-06-20 16:38:30 -07004147 /* Register with platform driver as client for Suspend/Resume */
4148 status = hddRegisterPmOps(pHddCtx);
4149 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4150 {
4151 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
4152#ifdef WLAN_BTAMP_FEATURE
4153 goto err_bap_stop;
4154#else
Jeff Johnsone7245742012-09-05 17:12:55 -07004155 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004156#endif //WLAN_BTAMP_FEATURE
4157 }
4158
4159 /* Register TM level change handler function to the platform */
4160 status = hddDevTmRegisterNotifyCallback(pHddCtx);
4161 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4162 {
4163 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
4164 goto err_unregister_pmops;
4165 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004166
4167 /* register for riva power on lock to platform driver */
4168 if (req_riva_power_on_lock("wlan"))
4169 {
4170 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
4171 __func__);
4172 goto err_unregister_pmops;
4173 }
4174
Jeff Johnson295189b2012-06-20 16:38:30 -07004175 // register net device notifier for device change notification
4176 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4177
4178 if(ret < 0)
4179 {
4180 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
4181 goto err_free_power_on_lock;
4182 }
4183
4184 //Initialize the nlink service
4185 if(nl_srv_init() != 0)
4186 {
4187 hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
4188 goto err_reg_netdev;
4189 }
4190
4191 //Initialize the BTC service
4192 if(btc_activate_service(pHddCtx) != 0)
4193 {
4194 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
4195 goto err_nl_srv;
4196 }
4197
4198#ifdef PTT_SOCK_SVC_ENABLE
4199 //Initialize the PTT service
4200 if(ptt_sock_activate_svc(pHddCtx) != 0)
4201 {
4202 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
4203 goto err_nl_srv;
4204 }
4205#endif
4206
Jeff Johnson295189b2012-06-20 16:38:30 -07004207 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004208 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004209 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07004210 /* Action frame registered in one adapter which will
4211 * applicable to all interfaces
4212 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07004213 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07004214 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004215
4216 mutex_init(&pHddCtx->sap_lock);
4217
4218 pHddCtx->isLoadUnloadInProgress = FALSE;
4219
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004220#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004221#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4222 /* Initialize the wake lcok */
4223 wake_lock_init(&pHddCtx->rx_wake_lock,
4224 WAKE_LOCK_SUSPEND,
4225 "qcom_rx_wakelock");
4226#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004227 /* Initialize the wake lcok */
4228 wake_lock_init(&pHddCtx->sap_wake_lock,
4229 WAKE_LOCK_SUSPEND,
4230 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004231#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004232
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004233 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
4234 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07004235
4236 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4237 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004238
4239 // Initialize the restart logic
4240 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05304241
4242#ifdef FEATURE_WLAN_TDLS
Hoonki Lee387663d2013-02-05 18:08:43 -08004243 if(0 != wlan_hdd_tdls_init(pAdapter->dev))
4244 {
4245 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_tdls_init failed",__func__);
4246 goto err_nl_srv;
4247 }
Chilam NG571c65a2013-01-19 12:27:36 +05304248#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004249
4250 goto success;
4251
4252err_nl_srv:
4253 nl_srv_exit();
4254
4255err_reg_netdev:
4256 unregister_netdevice_notifier(&hdd_netdev_notifier);
4257
4258err_free_power_on_lock:
4259 free_riva_power_on_lock("wlan");
4260
4261err_unregister_pmops:
4262 hddDevTmUnregisterNotifyCallback(pHddCtx);
4263 hddDeregisterPmOps(pHddCtx);
4264
4265#ifdef WLAN_BTAMP_FEATURE
4266err_bap_stop:
4267 WLANBAP_Stop(pVosContext);
4268#endif
4269
4270#ifdef WLAN_BTAMP_FEATURE
4271err_bap_close:
4272 WLANBAP_Close(pVosContext);
4273#endif
4274
Jeff Johnson295189b2012-06-20 16:38:30 -07004275err_close_adapter:
4276 hdd_close_all_adapters( pHddCtx );
4277
4278err_vosstop:
4279 vos_stop(pVosContext);
4280
4281err_vosclose:
4282 status = vos_sched_close( pVosContext );
4283 if (!VOS_IS_STATUS_SUCCESS(status)) {
4284 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4285 "%s: Failed to close VOSS Scheduler", __func__);
4286 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
4287 }
4288 vos_close(pVosContext );
4289
Jeff Johnson295189b2012-06-20 16:38:30 -07004290err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004291 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004292
4293err_wdclose:
4294 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4295 vos_watchdog_close(pVosContext);
4296
Jeff Johnson295189b2012-06-20 16:38:30 -07004297err_wiphy_reg:
4298 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004299
4300err_config:
4301 kfree(pHddCtx->cfg_ini);
4302 pHddCtx->cfg_ini= NULL;
4303
4304err_free_hdd_context:
4305 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004306 wiphy_free(wiphy) ;
4307 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004308 VOS_BUG(1);
4309
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08004310 if (hdd_is_ssr_required())
4311 {
4312 /* WDI timeout had happened during load, so SSR is needed here */
4313 subsystem_restart("wcnss");
4314 msleep(5000);
4315 }
4316 hdd_set_ssr_required (VOS_FALSE);
4317
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004318 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004319
4320success:
4321 EXIT();
4322 return 0;
4323}
4324
4325/**---------------------------------------------------------------------------
4326
Jeff Johnson32d95a32012-09-10 13:15:23 -07004327 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07004328
Jeff Johnson32d95a32012-09-10 13:15:23 -07004329 This is the driver entry point - called in different timeline depending
4330 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07004331
4332 \param - None
4333
4334 \return - 0 for success, non zero for failure
4335
4336 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07004337static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004338{
4339 VOS_STATUS status;
4340 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004341 struct device *dev = NULL;
4342 int ret_status = 0;
4343
4344 ENTER();
4345
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004346#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004347 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07004348#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004349
4350 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
4351 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
4352
4353 //Power Up Libra WLAN card first if not already powered up
4354 status = vos_chipPowerUp(NULL,NULL,NULL);
4355 if (!VOS_IS_STATUS_SUCCESS(status))
4356 {
4357 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
4358 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004359 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004360 }
4361
Jeff Johnson295189b2012-06-20 16:38:30 -07004362#ifdef ANI_BUS_TYPE_PCI
4363
4364 dev = wcnss_wlan_get_device();
4365
4366#endif // ANI_BUS_TYPE_PCI
4367
4368#ifdef ANI_BUS_TYPE_PLATFORM
4369 dev = wcnss_wlan_get_device();
4370#endif // ANI_BUS_TYPE_PLATFORM
4371
4372
4373 do {
4374 if (NULL == dev) {
4375 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
4376 ret_status = -1;
4377 break;
4378 }
4379
4380#ifdef MEMORY_DEBUG
4381 vos_mem_init();
4382#endif
4383
4384#ifdef TIMER_MANAGER
4385 vos_timer_manager_init();
4386#endif
4387
4388 /* Preopen VOSS so that it is ready to start at least SAL */
4389 status = vos_preOpen(&pVosContext);
4390
4391 if (!VOS_IS_STATUS_SUCCESS(status))
4392 {
4393 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
4394 ret_status = -1;
4395 break;
4396 }
4397
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004398#ifndef MODULE
4399 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
4400 */
4401 hdd_set_conparam((v_UINT_t)con_mode);
4402#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004403
4404 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004405 if (hdd_wlan_startup(dev))
4406 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004407 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004408 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004409 vos_preClose( &pVosContext );
4410 ret_status = -1;
4411 break;
4412 }
4413
4414 /* Cancel the vote for XO Core ON
4415 * This is done here for safety purposes in case we re-initialize without turning
4416 * it OFF in any error scenario.
4417 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004418 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07004419 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004420 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07004421 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4422 {
4423 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
4424 " Power consumed will be high\n");
4425 }
4426 } while (0);
4427
4428 if (0 != ret_status)
4429 {
4430 //Assert Deep sleep signal now to put Libra HW in lowest power state
4431 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4432 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
4433
4434 //Vote off any PMIC voltage supplies
4435 vos_chipPowerDown(NULL, NULL, NULL);
4436#ifdef TIMER_MANAGER
4437 vos_timer_exit();
4438#endif
4439#ifdef MEMORY_DEBUG
4440 vos_mem_exit();
4441#endif
4442
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004443#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004444 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004445#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004446 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
4447 }
4448 else
4449 {
4450 //Send WLAN UP indication to Nlink Service
4451 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
4452
4453 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
4454
4455 }
4456
4457 EXIT();
4458
4459 return ret_status;
4460}
4461
Jeff Johnson32d95a32012-09-10 13:15:23 -07004462/**---------------------------------------------------------------------------
4463
4464 \brief hdd_module_init() - Init Function
4465
4466 This is the driver entry point (invoked when module is loaded using insmod)
4467
4468 \param - None
4469
4470 \return - 0 for success, non zero for failure
4471
4472 --------------------------------------------------------------------------*/
4473#ifdef MODULE
4474static int __init hdd_module_init ( void)
4475{
4476 return hdd_driver_init();
4477}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004478#else /* #ifdef MODULE */
4479static int __init hdd_module_init ( void)
4480{
4481 /* Driver initialization is delayed to fwpath_changed_handler */
4482 return 0;
4483}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004484#endif /* #ifdef MODULE */
4485
Jeff Johnson295189b2012-06-20 16:38:30 -07004486
4487/**---------------------------------------------------------------------------
4488
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004489 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07004490
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004491 This is the driver exit point (invoked when module is unloaded using rmmod
4492 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07004493
4494 \param - None
4495
4496 \return - None
4497
4498 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004499static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004500{
4501 hdd_context_t *pHddCtx = NULL;
4502 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004503
4504 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
4505
4506 //Get the global vos context
4507 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4508
4509 if(!pVosContext)
4510 {
4511 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
4512 goto done;
4513 }
4514
4515 //Get the HDD context.
4516 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
4517
4518 if(!pHddCtx)
4519 {
4520 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
4521 }
4522 else
4523 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004524 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07004525 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07004526 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
4527 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07004528 }
4529
4530 pHddCtx->isLoadUnloadInProgress = TRUE;
4531 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4532
4533 //Do all the cleanup before deregistering the driver
4534 hdd_wlan_exit(pHddCtx);
4535 }
4536
Jeff Johnson295189b2012-06-20 16:38:30 -07004537 vos_preClose( &pVosContext );
4538
4539#ifdef TIMER_MANAGER
4540 vos_timer_exit();
4541#endif
4542#ifdef MEMORY_DEBUG
4543 vos_mem_exit();
4544#endif
4545
4546done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004547#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004548 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004549#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004550 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
4551}
4552
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004553/**---------------------------------------------------------------------------
4554
4555 \brief hdd_module_exit() - Exit function
4556
4557 This is the driver exit point (invoked when module is unloaded using rmmod)
4558
4559 \param - None
4560
4561 \return - None
4562
4563 --------------------------------------------------------------------------*/
4564static void __exit hdd_module_exit(void)
4565{
4566 hdd_driver_exit();
4567}
4568
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004569#ifdef MODULE
4570static int fwpath_changed_handler(const char *kmessage,
4571 struct kernel_param *kp)
4572{
4573 /* nothing to do when driver is DLKM */
4574 return 0;
4575}
4576
4577static int con_mode_handler(const char *kmessage,
4578 struct kernel_param *kp)
4579{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07004580 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004581}
4582#else /* #ifdef MODULE */
4583/**---------------------------------------------------------------------------
4584
4585 \brief fwpath_changed_handler() - Handler Function
4586
4587 This is the driver entry point
4588 - delayed driver initialization when driver is statically linked
4589 - invoked when module parameter fwpath is modified from userpspace to signal
4590 initializing the WLAN driver
4591
4592 \return - 0 for success, non zero for failure
4593
4594 --------------------------------------------------------------------------*/
4595static int fwpath_changed_handler(const char *kmessage,
4596 struct kernel_param *kp)
4597{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004598 int ret_status;
4599
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004600 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004601 ret_status = hdd_driver_init();
4602 wlan_hdd_inited = ret_status ? 0 : 1;
4603 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004604 }
4605
4606 hdd_driver_exit();
4607
4608 msleep(200);
4609
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004610 ret_status = hdd_driver_init();
4611 wlan_hdd_inited = ret_status ? 0 : 1;
4612 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004613}
4614
Jeff Johnson295189b2012-06-20 16:38:30 -07004615/**---------------------------------------------------------------------------
4616
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004617 \brief con_mode_handler() -
4618
4619 Handler function for module param con_mode when it is changed by userspace
4620 Dynamically linked - do nothing
4621 Statically linked - exit and init driver, as in rmmod and insmod
4622
4623 \param -
4624
4625 \return -
4626
4627 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004628static int con_mode_handler(const char *kmessage,
4629 struct kernel_param *kp)
4630{
4631 int ret = param_set_int(kmessage, kp);
4632
4633 if (ret)
4634 return ret;
4635
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004636 return fwpath_changed_handler(kmessage, kp);
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004637}
4638#endif /* #ifdef MODULE */
4639
4640/**---------------------------------------------------------------------------
4641
Jeff Johnson295189b2012-06-20 16:38:30 -07004642 \brief hdd_get_conparam() -
4643
4644 This is the driver exit point (invoked when module is unloaded using rmmod)
4645
4646 \param - None
4647
4648 \return - tVOS_CON_MODE
4649
4650 --------------------------------------------------------------------------*/
4651tVOS_CON_MODE hdd_get_conparam ( void )
4652{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004653#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07004654 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004655#else
4656 return (tVOS_CON_MODE)curr_con_mode;
4657#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004658}
4659void hdd_set_conparam ( v_UINT_t newParam )
4660{
4661 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004662#ifndef MODULE
4663 curr_con_mode = con_mode;
4664#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004665}
4666/**---------------------------------------------------------------------------
4667
4668 \brief hdd_softap_sta_deauth() - function
4669
4670 This to take counter measure to handle deauth req from HDD
4671
4672 \param - pAdapter - Pointer to the HDD
4673
4674 \param - enable - boolean value
4675
4676 \return - None
4677
4678 --------------------------------------------------------------------------*/
4679
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004680VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07004681{
Jeff Johnson295189b2012-06-20 16:38:30 -07004682 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004683 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07004684
4685 ENTER();
4686
4687 hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4688
4689 //Ignore request to deauth bcmc station
4690 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004691 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004692
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004693 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07004694
4695 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004696 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004697}
4698
4699/**---------------------------------------------------------------------------
4700
4701 \brief hdd_softap_sta_disassoc() - function
4702
4703 This to take counter measure to handle deauth req from HDD
4704
4705 \param - pAdapter - Pointer to the HDD
4706
4707 \param - enable - boolean value
4708
4709 \return - None
4710
4711 --------------------------------------------------------------------------*/
4712
4713void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
4714{
4715 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4716
4717 ENTER();
4718
4719 hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4720
4721 //Ignore request to disassoc bcmc station
4722 if( pDestMacAddress[0] & 0x1 )
4723 return;
4724
4725 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
4726}
4727
4728void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
4729{
4730 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4731
4732 ENTER();
4733
4734 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4735
4736 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
4737}
4738
Jeff Johnson295189b2012-06-20 16:38:30 -07004739/**---------------------------------------------------------------------------
4740 *
4741 * \brief hdd_get__concurrency_mode() -
4742 *
4743 *
4744 * \param - None
4745 *
4746 * \return - CONCURRENCY MODE
4747 *
4748 * --------------------------------------------------------------------------*/
4749tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
4750{
4751 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
4752 hdd_context_t *pHddCtx;
4753
4754 if (NULL != pVosContext)
4755 {
4756 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
4757 if (NULL != pHddCtx)
4758 {
4759 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
4760 }
4761 }
4762
4763 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004764 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004765 return VOS_STA;
4766}
4767
4768/* Decide whether to allow/not the apps power collapse.
4769 * Allow apps power collapse if we are in connected state.
4770 * if not, allow only if we are in IMPS */
4771v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
4772{
4773 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08004774 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07004775 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4776 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4777 hdd_adapter_t *pAdapter = NULL;
4778 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08004779 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004780
Jeff Johnson295189b2012-06-20 16:38:30 -07004781 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4782 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004783
Yathish9f22e662012-12-10 14:21:35 -08004784 concurrent_state = hdd_get_concurrency_mode();
4785
4786#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4787 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
4788 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
4789 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
4790 return TRUE;
4791#endif
4792
Jeff Johnson295189b2012-06-20 16:38:30 -07004793 /*loop through all adapters. TBD fix for Concurrency */
4794 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4795 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4796 {
4797 pAdapter = pAdapterNode->pAdapter;
4798 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4799 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4800 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08004801 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07004802 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08004803 && pmcState != STOPPED && pmcState != STANDBY)) ||
4804 (eANI_BOOLEAN_TRUE == scanRspPending))
Jeff Johnson295189b2012-06-20 16:38:30 -07004805 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08004806 hddLog( LOGE, "%s: do not allow APPS power collapse-"
4807 "pmcState = %d scanRspPending = %d",
4808 __func__, pmcState, scanRspPending );
Jeff Johnson295189b2012-06-20 16:38:30 -07004809 return FALSE;
4810 }
4811 }
4812 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4813 pAdapterNode = pNext;
4814 }
4815 return TRUE;
4816}
4817
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08004818/* Decides whether to send suspend notification to Riva
4819 * if any adapter is in BMPS; then it is required */
4820v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
4821{
4822 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
4823 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4824
4825 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
4826 {
4827 return TRUE;
4828 }
4829 return FALSE;
4830}
4831
Jeff Johnson295189b2012-06-20 16:38:30 -07004832void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
4833{
4834 switch(mode)
4835 {
4836 case WLAN_HDD_INFRA_STATION:
4837#ifdef WLAN_FEATURE_P2P
4838 case WLAN_HDD_P2P_CLIENT:
4839 case WLAN_HDD_P2P_GO:
4840#endif
4841 case WLAN_HDD_SOFTAP:
Jeff Johnsone7245742012-09-05 17:12:55 -07004842 pHddCtx->concurrency_mode |= (1 << mode);
4843 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07004844 break;
4845 default:
4846 break;
4847
4848 }
4849 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
4850 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
4851}
4852
4853
4854void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
4855{
4856 switch(mode)
4857 {
4858 case WLAN_HDD_INFRA_STATION:
4859#ifdef WLAN_FEATURE_P2P
4860 case WLAN_HDD_P2P_CLIENT:
4861 case WLAN_HDD_P2P_GO:
4862#endif
4863 case WLAN_HDD_SOFTAP:
4864 pHddCtx->no_of_sessions[mode]--;
4865 if (!(pHddCtx->no_of_sessions[mode]))
4866 pHddCtx->concurrency_mode &= (~(1 << mode));
4867 break;
4868 default:
4869 break;
4870 }
4871 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
4872 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
4873}
4874
Jeff Johnsone7245742012-09-05 17:12:55 -07004875/**---------------------------------------------------------------------------
4876 *
4877 * \brief wlan_hdd_restart_init
4878 *
4879 * This function initalizes restart timer/flag. An internal function.
4880 *
4881 * \param - pHddCtx
4882 *
4883 * \return - None
4884 *
4885 * --------------------------------------------------------------------------*/
4886
4887static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
4888{
4889 /* Initialize */
4890 pHddCtx->hdd_restart_retries = 0;
4891 atomic_set(&pHddCtx->isRestartInProgress, 0);
4892 vos_timer_init(&pHddCtx->hdd_restart_timer,
4893 VOS_TIMER_TYPE_SW,
4894 wlan_hdd_restart_timer_cb,
4895 pHddCtx);
4896}
4897/**---------------------------------------------------------------------------
4898 *
4899 * \brief wlan_hdd_restart_deinit
4900 *
4901 * This function cleans up the resources used. An internal function.
4902 *
4903 * \param - pHddCtx
4904 *
4905 * \return - None
4906 *
4907 * --------------------------------------------------------------------------*/
4908
4909static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
4910{
4911
4912 VOS_STATUS vos_status;
4913 /* Block any further calls */
4914 atomic_set(&pHddCtx->isRestartInProgress, 1);
4915 /* Cleanup */
4916 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
4917 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004918 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07004919 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
4920 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004921 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07004922
4923}
4924
4925/**---------------------------------------------------------------------------
4926 *
4927 * \brief wlan_hdd_framework_restart
4928 *
4929 * This function uses a cfg80211 API to start a framework initiated WLAN
4930 * driver module unload/load.
4931 *
4932 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
4933 *
4934 *
4935 * \param - pHddCtx
4936 *
4937 * \return - VOS_STATUS_SUCCESS: Success
4938 * VOS_STATUS_E_EMPTY: Adapter is Empty
4939 * VOS_STATUS_E_NOMEM: No memory
4940
4941 * --------------------------------------------------------------------------*/
4942
4943static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
4944{
4945 VOS_STATUS status = VOS_STATUS_SUCCESS;
4946 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4947 int len = (sizeof (struct ieee80211_mgmt));
4948 struct ieee80211_mgmt *mgmt = NULL;
4949
4950 /* Prepare the DEAUTH managment frame with reason code */
4951 mgmt = kzalloc(len, GFP_KERNEL);
4952 if(mgmt == NULL)
4953 {
4954 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1250df42012-12-10 14:31:52 -08004955 "%s: memory allocation failed (%d bytes)", __func__, len);
Jeff Johnsone7245742012-09-05 17:12:55 -07004956 return VOS_STATUS_E_NOMEM;
4957 }
4958 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
4959
4960 /* Iterate over all adapters/devices */
4961 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4962 do
4963 {
4964 if( (status == VOS_STATUS_SUCCESS) &&
4965 pAdapterNode &&
4966 pAdapterNode->pAdapter)
4967 {
4968 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4969 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
4970 pAdapterNode->pAdapter->dev->name,
4971 pAdapterNode->pAdapter->device_mode,
4972 pHddCtx->hdd_restart_retries + 1);
4973 /*
4974 * CFG80211 event to restart the driver
4975 *
4976 * 'cfg80211_send_unprot_deauth' sends a
4977 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
4978 * of SME(Linux Kernel) state machine.
4979 *
4980 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
4981 * the driver.
4982 *
4983 */
4984
4985 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
4986 }
4987 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4988 pAdapterNode = pNext;
4989 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
4990
4991
4992 /* Free the allocated management frame */
4993 kfree(mgmt);
4994
4995 /* Retry until we unload or reach max count */
4996 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
4997 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
4998
4999 return status;
5000
5001}
5002/**---------------------------------------------------------------------------
5003 *
5004 * \brief wlan_hdd_restart_timer_cb
5005 *
5006 * Restart timer callback. An internal function.
5007 *
5008 * \param - User data:
5009 *
5010 * \return - None
5011 *
5012 * --------------------------------------------------------------------------*/
5013
5014void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
5015{
5016 hdd_context_t *pHddCtx = usrDataForCallback;
5017 wlan_hdd_framework_restart(pHddCtx);
5018 return;
5019
5020}
5021
5022
5023/**---------------------------------------------------------------------------
5024 *
5025 * \brief wlan_hdd_restart_driver
5026 *
5027 * This function sends an event to supplicant to restart the WLAN driver.
5028 *
5029 * This function is called from vos_wlanRestart.
5030 *
5031 * \param - pHddCtx
5032 *
5033 * \return - VOS_STATUS_SUCCESS: Success
5034 * VOS_STATUS_E_EMPTY: Adapter is Empty
5035 * VOS_STATUS_E_ALREADY: Request already in progress
5036
5037 * --------------------------------------------------------------------------*/
5038VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
5039{
5040 VOS_STATUS status = VOS_STATUS_SUCCESS;
5041
5042 /* A tight check to make sure reentrancy */
5043 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
5044 {
5045 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
5046 "%s: WLAN restart is already in progress", __func__);
5047
5048 return VOS_STATUS_E_ALREADY;
5049 }
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005050 /* when WLAN driver is statically linked, then invoke SSR by sending
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005051 * the reset interrupt. If it is DLKM, then use restart API
5052 */
5053#ifdef MODULE
Jeff Johnsone7245742012-09-05 17:12:55 -07005054 status = wlan_hdd_framework_restart(pHddCtx);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005055#else
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005056#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005057 wcnss_reset_intr();
5058#endif
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005059#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005060
Jeff Johnsone7245742012-09-05 17:12:55 -07005061 return status;
5062}
5063
5064
Jeff Johnson295189b2012-06-20 16:38:30 -07005065//Register the module init/exit functions
5066module_init(hdd_module_init);
5067module_exit(hdd_module_exit);
5068
5069MODULE_LICENSE("Dual BSD/GPL");
5070MODULE_AUTHOR("Qualcomm Atheros, Inc.");
5071MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
5072
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005073module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
5074 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07005075
5076module_param_call(fwpath, fwpath_changed_handler, param_get_string, fwpath,
5077 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);