blob: 98f6e7f256bf859e241183d02b97ebcf2306fc10 [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 )
Jeff Johnson295189b2012-06-20 16:38:30 -07001195 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001196 )
1197 {
1198 /* SoftAP mode, so return from here */
1199 EXIT();
1200 return 0;
1201 }
1202
1203 /* Find if any iface is up then
1204 if any iface is up then can't put device to sleep/ power save mode. */
1205 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1206 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1207 {
1208 if ( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
1209 {
1210 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
1211 "put device to sleep", __func__, pAdapter->device_mode);
1212 enter_standby = FALSE;
1213 break;
1214 }
1215 else
1216 {
1217 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1218 pAdapterNode = pNext;
1219 }
1220 }
1221
1222 if (TRUE == enter_standby)
1223 {
1224 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
1225 "entering standby", __func__);
1226 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
1227 {
1228 /*log and return success*/
1229 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
1230 "wlan in power save", __func__);
1231 }
1232 }
1233
1234 EXIT();
1235 return 0;
1236}
1237
1238/**---------------------------------------------------------------------------
1239
1240 \brief hdd_uninit() - HDD uninit function
1241
1242 This is called during the netdev unregister to uninitialize all data
1243associated with the device
1244
1245 \param - dev Pointer to net_device structure
1246
1247 \return - void
1248
1249 --------------------------------------------------------------------------*/
1250static void hdd_uninit (struct net_device *dev)
1251{
1252 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1253
1254 ENTER();
1255
1256 do
1257 {
1258 if (NULL == pAdapter)
1259 {
1260 hddLog(VOS_TRACE_LEVEL_FATAL,
1261 "%s: NULL pAdapter", __func__);
1262 break;
1263 }
1264
1265 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1266 {
1267 hddLog(VOS_TRACE_LEVEL_FATAL,
1268 "%s: Invalid magic", __func__);
1269 break;
1270 }
1271
1272 if (NULL == pAdapter->pHddCtx)
1273 {
1274 hddLog(VOS_TRACE_LEVEL_FATAL,
1275 "%s: NULL pHddCtx", __func__);
1276 break;
1277 }
1278
1279 if (dev != pAdapter->dev)
1280 {
1281 hddLog(VOS_TRACE_LEVEL_FATAL,
1282 "%s: Invalid device reference", __func__);
1283 /* we haven't validated all cases so let this go for now */
1284 }
1285
1286 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
1287
1288 /* after uninit our adapter structure will no longer be valid */
1289 pAdapter->dev = NULL;
1290 pAdapter->magic = 0;
1291 } while (0);
1292
1293 EXIT();
1294}
1295
1296/**---------------------------------------------------------------------------
1297
1298 \brief hdd_release_firmware() -
1299
1300 This function calls the release firmware API to free the firmware buffer.
1301
1302 \param - pFileName Pointer to the File Name.
1303 pCtx - Pointer to the adapter .
1304
1305
1306 \return - 0 for success, non zero for failure
1307
1308 --------------------------------------------------------------------------*/
1309
1310VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
1311{
1312 VOS_STATUS status = VOS_STATUS_SUCCESS;
1313 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1314 ENTER();
1315
1316
1317 if (!strcmp(WLAN_FW_FILE, pFileName)) {
1318
1319 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
1320
1321 if(pHddCtx->fw) {
1322 release_firmware(pHddCtx->fw);
1323 pHddCtx->fw = NULL;
1324 }
1325 else
1326 status = VOS_STATUS_E_FAILURE;
1327 }
1328 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
1329 if(pHddCtx->nv) {
1330 release_firmware(pHddCtx->nv);
1331 pHddCtx->nv = NULL;
1332 }
1333 else
1334 status = VOS_STATUS_E_FAILURE;
1335
1336 }
1337
1338 EXIT();
1339 return status;
1340}
1341
1342/**---------------------------------------------------------------------------
1343
1344 \brief hdd_request_firmware() -
1345
1346 This function reads the firmware file using the request firmware
1347 API and returns the the firmware data and the firmware file size.
1348
1349 \param - pfileName - Pointer to the file name.
1350 - pCtx - Pointer to the adapter .
1351 - ppfw_data - Pointer to the pointer of the firmware data.
1352 - pSize - Pointer to the file size.
1353
1354 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
1355
1356 --------------------------------------------------------------------------*/
1357
1358
1359VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
1360{
1361 int status;
1362 VOS_STATUS retval = VOS_STATUS_SUCCESS;
1363 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1364 ENTER();
1365
1366 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
1367
1368 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
1369
1370 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1371 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
1372 __func__, pfileName);
1373 retval = VOS_STATUS_E_FAILURE;
1374 }
1375
1376 else {
1377 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
1378 *pSize = pHddCtx->fw->size;
1379 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
1380 __func__, *pSize);
1381 }
1382 }
1383 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
1384
1385 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
1386
1387 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
1388 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
1389 __func__, pfileName);
1390 retval = VOS_STATUS_E_FAILURE;
1391 }
1392
1393 else {
1394 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
1395 *pSize = pHddCtx->nv->size;
1396 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
1397 __func__, *pSize);
1398 }
1399 }
1400
1401 EXIT();
1402 return retval;
1403}
1404/**---------------------------------------------------------------------------
1405 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
1406
1407 This is the function invoked by SME to inform the result of a full power
1408 request issued by HDD
1409
1410 \param - callbackcontext - Pointer to cookie
1411 status - result of request
1412
1413 \return - None
1414
1415--------------------------------------------------------------------------*/
1416void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
1417{
1418 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
1419
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001420 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001421 if(&pHddCtx->full_pwr_comp_var)
1422 {
1423 complete(&pHddCtx->full_pwr_comp_var);
1424 }
1425}
1426
1427/**---------------------------------------------------------------------------
1428
1429 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
1430
1431 This is the function invoked by SME to inform the result of BMPS
1432 request issued by HDD
1433
1434 \param - callbackcontext - Pointer to cookie
1435 status - result of request
1436
1437 \return - None
1438
1439--------------------------------------------------------------------------*/
1440void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
1441{
1442
1443 struct completion *completion_var = (struct completion*) callbackContext;
1444
1445 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
1446 if(completion_var != NULL)
1447 {
1448 complete(completion_var);
1449 }
1450}
1451
1452/**---------------------------------------------------------------------------
1453
1454 \brief hdd_get_cfg_file_size() -
1455
1456 This function reads the configuration file using the request firmware
1457 API and returns the configuration file size.
1458
1459 \param - pCtx - Pointer to the adapter .
1460 - pFileName - Pointer to the file name.
1461 - pBufSize - Pointer to the buffer size.
1462
1463 \return - 0 for success, non zero for failure
1464
1465 --------------------------------------------------------------------------*/
1466
1467VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
1468{
1469 int status;
1470 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1471
1472 ENTER();
1473
1474 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
1475
1476 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1477 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
1478 status = VOS_STATUS_E_FAILURE;
1479 }
1480 else {
1481 *pBufSize = pHddCtx->fw->size;
1482 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
1483 release_firmware(pHddCtx->fw);
1484 pHddCtx->fw = NULL;
1485 }
1486
1487 EXIT();
1488 return VOS_STATUS_SUCCESS;
1489}
1490
1491/**---------------------------------------------------------------------------
1492
1493 \brief hdd_read_cfg_file() -
1494
1495 This function reads the configuration file using the request firmware
1496 API and returns the cfg data and the buffer size of the configuration file.
1497
1498 \param - pCtx - Pointer to the adapter .
1499 - pFileName - Pointer to the file name.
1500 - pBuffer - Pointer to the data buffer.
1501 - pBufSize - Pointer to the buffer size.
1502
1503 \return - 0 for success, non zero for failure
1504
1505 --------------------------------------------------------------------------*/
1506
1507VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
1508 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
1509{
1510 int status;
1511 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1512
1513 ENTER();
1514
1515 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
1516
1517 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1518 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
1519 return VOS_STATUS_E_FAILURE;
1520 }
1521 else {
1522 if(*pBufSize != pHddCtx->fw->size) {
1523 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
1524 "file size", __func__);
1525 release_firmware(pHddCtx->fw);
1526 pHddCtx->fw = NULL;
1527 return VOS_STATUS_E_FAILURE;
1528 }
1529 else {
1530 if(pBuffer) {
1531 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
1532 }
1533 release_firmware(pHddCtx->fw);
1534 pHddCtx->fw = NULL;
1535 }
1536 }
1537
1538 EXIT();
1539
1540 return VOS_STATUS_SUCCESS;
1541}
1542
1543/**---------------------------------------------------------------------------
1544
Jeff Johnson295189b2012-06-20 16:38:30 -07001545 \brief hdd_set_mac_address() -
1546
1547 This function sets the user specified mac address using
1548 the command ifconfig wlanX hw ether <mac adress>.
1549
1550 \param - dev - Pointer to the net device.
1551 - addr - Pointer to the sockaddr.
1552 \return - 0 for success, non zero for failure
1553
1554 --------------------------------------------------------------------------*/
1555
1556static int hdd_set_mac_address(struct net_device *dev, void *addr)
1557{
1558 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1559 struct sockaddr *psta_mac_addr = addr;
1560 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1561
1562 ENTER();
1563
1564 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
1565
1566#ifdef HDD_SESSIONIZE
1567 // set the MAC address though the STA ID CFG.
1568 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
1569 (v_U8_t *)&pAdapter->macAddressCurrent,
1570 sizeof( pAdapter->macAddressCurrent ),
1571 hdd_set_mac_addr_cb, VOS_FALSE );
1572#endif
1573
1574 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
1575
1576 EXIT();
1577 return halStatus;
1578}
1579
1580tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
1581{
1582 int i;
1583 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
1584 {
1585 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
1586 break;
1587 }
1588
1589 if( VOS_MAX_CONCURRENCY_PERSONA == i)
1590 return NULL;
1591
1592 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
1593 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
1594}
1595
1596void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
1597{
1598 int i;
1599 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
1600 {
1601 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
1602 {
1603 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
1604 break;
1605 }
1606 }
1607 return;
1608}
1609
1610#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1611 static struct net_device_ops wlan_drv_ops = {
1612 .ndo_open = hdd_open,
1613 .ndo_stop = hdd_stop,
1614 .ndo_uninit = hdd_uninit,
1615 .ndo_start_xmit = hdd_hard_start_xmit,
1616 .ndo_tx_timeout = hdd_tx_timeout,
1617 .ndo_get_stats = hdd_stats,
1618 .ndo_do_ioctl = hdd_ioctl,
1619 .ndo_set_mac_address = hdd_set_mac_address,
1620 .ndo_select_queue = hdd_select_queue,
1621#ifdef WLAN_FEATURE_PACKET_FILTERING
1622#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
1623 .ndo_set_rx_mode = hdd_set_multicast_list,
1624#else
1625 .ndo_set_multicast_list = hdd_set_multicast_list,
1626#endif //LINUX_VERSION_CODE
1627#endif
1628 };
Jeff Johnson295189b2012-06-20 16:38:30 -07001629 static struct net_device_ops wlan_mon_drv_ops = {
1630 .ndo_open = hdd_mon_open,
1631 .ndo_stop = hdd_stop,
1632 .ndo_uninit = hdd_uninit,
1633 .ndo_start_xmit = hdd_mon_hard_start_xmit,
1634 .ndo_tx_timeout = hdd_tx_timeout,
1635 .ndo_get_stats = hdd_stats,
1636 .ndo_do_ioctl = hdd_ioctl,
1637 .ndo_set_mac_address = hdd_set_mac_address,
1638 };
Jeff Johnson295189b2012-06-20 16:38:30 -07001639
1640#endif
1641
1642void hdd_set_station_ops( struct net_device *pWlanDev )
1643{
1644#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1645 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
1646 pWlanDev->netdev_ops = &wlan_drv_ops;
1647#else
1648 pWlanDev->open = hdd_open;
1649 pWlanDev->stop = hdd_stop;
1650 pWlanDev->uninit = hdd_uninit;
1651 pWlanDev->hard_start_xmit = NULL;
1652 pWlanDev->tx_timeout = hdd_tx_timeout;
1653 pWlanDev->get_stats = hdd_stats;
1654 pWlanDev->do_ioctl = hdd_ioctl;
1655 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
1656 pWlanDev->set_mac_address = hdd_set_mac_address;
1657#endif
1658}
1659
Jeff Johnsoneed415b2013-01-18 16:11:20 -08001660static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07001661{
1662 struct net_device *pWlanDev = NULL;
1663 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001664 /*
1665 * cfg80211 initialization and registration....
1666 */
1667 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
1668
Jeff Johnson295189b2012-06-20 16:38:30 -07001669 if(pWlanDev != NULL)
1670 {
1671
1672 //Save the pointer to the net_device in the HDD adapter
1673 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
1674
Jeff Johnson295189b2012-06-20 16:38:30 -07001675 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
1676
1677 pAdapter->dev = pWlanDev;
1678 pAdapter->pHddCtx = pHddCtx;
1679 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
1680
1681 init_completion(&pAdapter->session_open_comp_var);
1682 init_completion(&pAdapter->session_close_comp_var);
1683 init_completion(&pAdapter->disconnect_comp_var);
1684 init_completion(&pAdapter->linkup_event_var);
1685 init_completion(&pAdapter->cancel_rem_on_chan_var);
1686 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001687#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1688 init_completion(&pAdapter->offchannel_tx_event);
1689#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001690 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08001691#ifdef FEATURE_WLAN_TDLS
1692 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001693 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08001694#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001695 init_completion(&pHddCtx->mc_sus_event_var);
1696 init_completion(&pHddCtx->tx_sus_event_var);
1697
Jeff Johnson295189b2012-06-20 16:38:30 -07001698 pAdapter->isLinkUpSvcNeeded = FALSE;
1699 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
1700 //Init the net_device structure
1701 strlcpy(pWlanDev->name, name, IFNAMSIZ);
1702
1703 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
1704 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
1705 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
1706 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
1707
1708 hdd_set_station_ops( pAdapter->dev );
1709
1710 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07001711 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
1712 pAdapter->wdev.wiphy = pHddCtx->wiphy;
1713 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07001714 /* set pWlanDev's parent to underlying device */
1715 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
1716 }
1717
1718 return pAdapter;
1719}
1720
1721VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
1722{
1723 struct net_device *pWlanDev = pAdapter->dev;
1724 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1725 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1726 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1727
1728 if( rtnl_lock_held )
1729 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001730 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07001731 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
1732 {
1733 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
1734 return VOS_STATUS_E_FAILURE;
1735 }
1736 }
1737 if (register_netdevice(pWlanDev))
1738 {
1739 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
1740 return VOS_STATUS_E_FAILURE;
1741 }
1742 }
1743 else
1744 {
1745 if(register_netdev(pWlanDev))
1746 {
1747 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
1748 return VOS_STATUS_E_FAILURE;
1749 }
1750 }
1751 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
1752
1753 return VOS_STATUS_SUCCESS;
1754}
1755
1756eHalStatus hdd_smeCloseSessionCallback(void *pContext)
1757{
1758 if(pContext != NULL)
1759 {
1760 clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags);
1761
1762 /* need to make sure all of our scheduled work has completed.
1763 * This callback is called from MC thread context, so it is safe to
1764 * to call below flush workqueue API from here.
1765 */
1766 flush_scheduled_work();
1767 complete(&((hdd_adapter_t*)pContext)->session_close_comp_var);
1768 }
1769 return eHAL_STATUS_SUCCESS;
1770}
1771
1772VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
1773{
1774 struct net_device *pWlanDev = pAdapter->dev;
1775 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1776 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1777 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1778 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1779 int rc = 0;
1780
1781 INIT_COMPLETION(pAdapter->session_open_comp_var);
1782 //Open a SME session for future operation
1783 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
1784 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
1785 if ( !HAL_STATUS_SUCCESS( halStatus ) )
1786 {
1787 hddLog(VOS_TRACE_LEVEL_FATAL,
1788 "sme_OpenSession() failed with status code %08d [x%08lx]",
1789 halStatus, halStatus );
1790 status = VOS_STATUS_E_FAILURE;
1791 goto error_sme_open;
1792 }
1793
1794 //Block on a completion variable. Can't wait forever though.
1795 rc = wait_for_completion_interruptible_timeout(
1796 &pAdapter->session_open_comp_var,
1797 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1798 if (!rc)
1799 {
1800 hddLog(VOS_TRACE_LEVEL_FATAL,
1801 "Session is not opened within timeout period code %08d", rc );
1802 status = VOS_STATUS_E_FAILURE;
1803 goto error_sme_open;
1804 }
1805
1806 // Register wireless extensions
1807 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
1808 {
1809 hddLog(VOS_TRACE_LEVEL_FATAL,
1810 "hdd_register_wext() failed with status code %08d [x%08lx]",
1811 halStatus, halStatus );
1812 status = VOS_STATUS_E_FAILURE;
1813 goto error_register_wext;
1814 }
1815 //Safe to register the hard_start_xmit function again
1816#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1817 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
1818#else
1819 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
1820#endif
1821
1822 //Set the Connection State to Not Connected
1823 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
1824
1825 //Set the default operation channel
1826 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
1827
1828 /* Make the default Auth Type as OPEN*/
1829 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
1830
1831 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
1832 {
1833 hddLog(VOS_TRACE_LEVEL_FATAL,
1834 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
1835 status, status );
1836 goto error_init_txrx;
1837 }
1838
1839 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1840
1841 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
1842 {
1843 hddLog(VOS_TRACE_LEVEL_FATAL,
1844 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
1845 status, status );
1846 goto error_wmm_init;
1847 }
1848
1849 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1850
1851 return VOS_STATUS_SUCCESS;
1852
1853error_wmm_init:
1854 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1855 hdd_deinit_tx_rx(pAdapter);
1856error_init_txrx:
1857 hdd_UnregisterWext(pWlanDev);
1858error_register_wext:
1859 if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
1860 {
1861 INIT_COMPLETION(pAdapter->session_close_comp_var);
1862 if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
1863 pAdapter->sessionId,
1864 hdd_smeCloseSessionCallback, pAdapter ) )
1865 {
1866 //Block on a completion variable. Can't wait forever though.
1867 wait_for_completion_interruptible_timeout(
1868 &pAdapter->session_close_comp_var,
1869 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1870 }
1871}
1872error_sme_open:
1873 return status;
1874}
1875
Jeff Johnson295189b2012-06-20 16:38:30 -07001876void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1877{
1878 hdd_cfg80211_state_t *cfgState;
1879
1880 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1881
1882 if( NULL != cfgState->buf )
1883 {
1884 int rc;
1885 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
1886 rc = wait_for_completion_interruptible_timeout(
1887 &pAdapter->tx_action_cnf_event,
1888 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
1889 if(!rc)
1890 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08001891 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001892 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
1893 }
1894 }
1895 return;
1896}
Jeff Johnson295189b2012-06-20 16:38:30 -07001897
1898void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1899{
1900 ENTER();
1901 switch ( pAdapter->device_mode )
1902 {
1903 case WLAN_HDD_INFRA_STATION:
1904 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07001905 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07001906 {
1907 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1908 {
1909 hdd_deinit_tx_rx( pAdapter );
1910 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1911 }
1912
1913 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
1914 {
1915 hdd_wmm_adapter_close( pAdapter );
1916 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1917 }
1918
Jeff Johnson295189b2012-06-20 16:38:30 -07001919 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001920
1921 break;
1922 }
1923
1924 case WLAN_HDD_SOFTAP:
1925 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07001926 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001927 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001928
1929 hdd_unregister_hostapd(pAdapter);
1930 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07001931 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07001932 break;
1933 }
1934
1935 case WLAN_HDD_MONITOR:
1936 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001937 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07001938 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1939 {
1940 hdd_deinit_tx_rx( pAdapter );
1941 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1942 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001943 if(NULL != pAdapterforTx)
1944 {
1945 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
1946 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001947 break;
1948 }
1949
1950
1951 default:
1952 break;
1953 }
1954
1955 EXIT();
1956}
1957
1958void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
1959{
1960 struct net_device *pWlanDev = pAdapter->dev;
1961
1962 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
1963 if( rtnl_held )
1964 {
1965 unregister_netdevice(pWlanDev);
1966 }
1967 else
1968 {
1969 unregister_netdev(pWlanDev);
1970 }
1971 // note that the pAdapter is no longer valid at this point
1972 // since the memory has been reclaimed
1973 }
1974
1975}
1976
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08001977void hdd_set_pwrparams(hdd_context_t *pHddCtx)
1978{
1979 tSirSetPowerParamsReq powerRequest = { 0 };
1980
1981 powerRequest.uIgnoreDTIM = 1;
1982
1983 if (pHddCtx->cfg_ini->enableModulatedDTIM)
1984 {
1985 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
1986 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
1987 }
1988 else
1989 {
1990 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
1991 }
1992
1993 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
1994 *specified during Enter/Exit BMPS when LCD off*/
1995 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1996 NULL, eANI_BOOLEAN_FALSE);
1997 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1998 NULL, eANI_BOOLEAN_FALSE);
1999
2000 /* switch to the DTIM specified in cfg.ini */
2001 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2002 "Switch to DTIM%d", powerRequest.uListenInterval);
2003 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2004
2005}
2006
2007void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
2008{
2009 /*Switch back to DTIM 1*/
2010 tSirSetPowerParamsReq powerRequest = { 0 };
2011
2012 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
2013 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2014
2015 /* Update ignoreDTIM and ListedInterval in CFG with default values */
2016 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2017 NULL, eANI_BOOLEAN_FALSE);
2018 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2019 NULL, eANI_BOOLEAN_FALSE);
2020
2021 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2022 "Switch to DTIM%d",powerRequest.uListenInterval);
2023 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2024
2025}
2026
Jeff Johnson295189b2012-06-20 16:38:30 -07002027VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
2028{
2029 VOS_STATUS status = VOS_STATUS_SUCCESS;
2030
2031 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2032 {
2033 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2034 }
2035
2036 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2037 {
2038 sme_StartAutoBmpsTimer(pHddCtx->hHal);
2039 }
2040
2041 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2042 {
2043 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2044 }
2045
2046 return status;
2047}
2048
2049VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
2050{
2051 hdd_adapter_t *pAdapter = NULL;
2052 eHalStatus halStatus;
2053 VOS_STATUS status = VOS_STATUS_E_INVAL;
2054 v_BOOL_t disableBmps = FALSE;
2055 v_BOOL_t disableImps = FALSE;
2056
2057 switch(session_type)
2058 {
2059 case WLAN_HDD_INFRA_STATION:
2060 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002061 case WLAN_HDD_P2P_CLIENT:
2062 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002063 //Exit BMPS -> Is Sta/P2P Client is already connected
2064 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
2065 if((NULL != pAdapter)&&
2066 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2067 {
2068 disableBmps = TRUE;
2069 }
2070
2071 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
2072 if((NULL != pAdapter)&&
2073 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2074 {
2075 disableBmps = TRUE;
2076 }
2077
2078 //Exit both Bmps and Imps incase of Go/SAP Mode
2079 if((WLAN_HDD_SOFTAP == session_type) ||
2080 (WLAN_HDD_P2P_GO == session_type))
2081 {
2082 disableBmps = TRUE;
2083 disableImps = TRUE;
2084 }
2085
2086 if(TRUE == disableImps)
2087 {
2088 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2089 {
2090 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2091 }
2092 }
2093
2094 if(TRUE == disableBmps)
2095 {
2096 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2097 {
2098 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2099
2100 if(eHAL_STATUS_SUCCESS != halStatus)
2101 {
2102 status = VOS_STATUS_E_FAILURE;
2103 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
2104 VOS_ASSERT(0);
2105 return status;
2106 }
2107 }
2108
2109 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2110 {
2111 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
2112
2113 if(eHAL_STATUS_SUCCESS != halStatus)
2114 {
2115 status = VOS_STATUS_E_FAILURE;
2116 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
2117 VOS_ASSERT(0);
2118 return status;
2119 }
2120 }
2121 }
2122
2123 if((TRUE == disableBmps) ||
2124 (TRUE == disableImps))
2125 {
2126 /* Now, get the chip into Full Power now */
2127 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
2128 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
2129 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
2130
2131 if(halStatus != eHAL_STATUS_SUCCESS)
2132 {
2133 if(halStatus == eHAL_STATUS_PMC_PENDING)
2134 {
2135 //Block on a completion variable. Can't wait forever though
2136 wait_for_completion_interruptible_timeout(
2137 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
2138 }
2139 else
2140 {
2141 status = VOS_STATUS_E_FAILURE;
2142 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
2143 VOS_ASSERT(0);
2144 return status;
2145 }
2146 }
2147
2148 status = VOS_STATUS_SUCCESS;
2149 }
2150
2151 break;
2152 }
2153 return status;
2154}
2155
2156hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002157 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07002158 tANI_U8 rtnl_held )
2159{
2160 hdd_adapter_t *pAdapter = NULL;
2161 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
2162 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2163 VOS_STATUS exitbmpsStatus;
2164
2165 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
2166
2167 //Disable BMPS incase of Concurrency
2168 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
2169
2170 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
2171 {
2172 //Fail to Exit BMPS
2173 VOS_ASSERT(0);
2174 return NULL;
2175 }
2176
2177 switch(session_type)
2178 {
2179 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002180 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002181 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002182 {
2183 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2184
2185 if( NULL == pAdapter )
2186 return NULL;
2187
Jeff Johnsone7245742012-09-05 17:12:55 -07002188 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
2189 NL80211_IFTYPE_P2P_CLIENT:
2190 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07002191
Jeff Johnson295189b2012-06-20 16:38:30 -07002192 pAdapter->device_mode = session_type;
2193
2194 status = hdd_init_station_mode( pAdapter );
2195 if( VOS_STATUS_SUCCESS != status )
2196 goto err_free_netdev;
2197
2198 status = hdd_register_interface( pAdapter, rtnl_held );
2199 if( VOS_STATUS_SUCCESS != status )
2200 {
2201 hdd_deinit_adapter(pHddCtx, pAdapter);
2202 goto err_free_netdev;
2203 }
2204 //Stop the Interface TX queue.
2205 netif_tx_disable(pAdapter->dev);
2206 //netif_tx_disable(pWlanDev);
2207 netif_carrier_off(pAdapter->dev);
2208
2209 break;
2210 }
2211
Jeff Johnson295189b2012-06-20 16:38:30 -07002212 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002213 case WLAN_HDD_SOFTAP:
2214 {
2215 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
2216 if( NULL == pAdapter )
2217 return NULL;
2218
Jeff Johnson295189b2012-06-20 16:38:30 -07002219 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
2220 NL80211_IFTYPE_AP:
2221 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002222 pAdapter->device_mode = session_type;
2223
2224 status = hdd_init_ap_mode(pAdapter);
2225 if( VOS_STATUS_SUCCESS != status )
2226 goto err_free_netdev;
2227
2228 status = hdd_register_hostapd( pAdapter, rtnl_held );
2229 if( VOS_STATUS_SUCCESS != status )
2230 {
2231 hdd_deinit_adapter(pHddCtx, pAdapter);
2232 goto err_free_netdev;
2233 }
2234
2235 netif_tx_disable(pAdapter->dev);
2236 netif_carrier_off(pAdapter->dev);
2237
2238 hdd_set_conparam( 1 );
2239 break;
2240 }
2241 case WLAN_HDD_MONITOR:
2242 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002243 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2244 if( NULL == pAdapter )
2245 return NULL;
2246
2247 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
2248 pAdapter->device_mode = session_type;
2249 status = hdd_register_interface( pAdapter, rtnl_held );
2250#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
2251 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
2252#else
2253 pAdapter->dev->open = hdd_mon_open;
2254 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
2255#endif
2256 hdd_init_tx_rx( pAdapter );
2257 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2258 //Set adapter to be used for data tx. It will use either GO or softap.
2259 pAdapter->sessionCtx.monitor.pAdapterForTx =
2260 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07002261 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
2262 {
2263 pAdapter->sessionCtx.monitor.pAdapterForTx =
2264 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
2265 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002266 /* This workqueue will be used to transmit management packet over
2267 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07002268 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
2269 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
2270 return NULL;
2271 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07002272
Jeff Johnson295189b2012-06-20 16:38:30 -07002273 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
2274 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07002275 }
2276 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002277 case WLAN_HDD_FTM:
2278 {
2279 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2280
2281 if( NULL == pAdapter )
2282 return NULL;
2283 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
2284 * message while loading driver in FTM mode. */
2285 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
2286 pAdapter->device_mode = session_type;
2287 status = hdd_register_interface( pAdapter, rtnl_held );
2288 }
2289 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002290 default:
2291 {
2292 VOS_ASSERT(0);
2293 return NULL;
2294 }
2295 }
2296
2297
2298 if( VOS_STATUS_SUCCESS == status )
2299 {
2300 //Add it to the hdd's session list.
2301 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
2302 if( NULL == pHddAdapterNode )
2303 {
2304 status = VOS_STATUS_E_NOMEM;
2305 }
2306 else
2307 {
2308 pHddAdapterNode->pAdapter = pAdapter;
2309 status = hdd_add_adapter_back ( pHddCtx,
2310 pHddAdapterNode );
2311 }
2312 }
2313
2314 if( VOS_STATUS_SUCCESS != status )
2315 {
2316 if( NULL != pAdapter )
2317 {
2318 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
2319 pAdapter = NULL;
2320 }
2321 if( NULL != pHddAdapterNode )
2322 {
2323 vos_mem_free( pHddAdapterNode );
2324 }
2325
2326 goto resume_bmps;
2327 }
2328
2329 if(VOS_STATUS_SUCCESS == status)
2330 {
2331 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
2332
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07002333 //Initialize the WoWL service
2334 if(!hdd_init_wowl(pAdapter))
2335 {
2336 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
2337 goto err_free_netdev;
2338 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002339 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002340 return pAdapter;
2341
2342err_free_netdev:
2343 free_netdev(pAdapter->dev);
2344 wlan_hdd_release_intf_addr( pHddCtx,
2345 pAdapter->macAddressCurrent.bytes );
2346
2347resume_bmps:
2348 //If bmps disabled enable it
2349 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
2350 {
2351 hdd_enable_bmps_imps(pHddCtx);
2352 }
2353 return NULL;
2354}
2355
2356VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
2357 tANI_U8 rtnl_held )
2358{
2359 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
2360 VOS_STATUS status;
2361
2362 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
2363 if( VOS_STATUS_SUCCESS != status )
2364 return status;
2365
2366 while ( pCurrent->pAdapter != pAdapter )
2367 {
2368 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
2369 if( VOS_STATUS_SUCCESS != status )
2370 break;
2371
2372 pCurrent = pNext;
2373 }
2374 pAdapterNode = pCurrent;
2375 if( VOS_STATUS_SUCCESS == status )
2376 {
2377 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2378 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
2379 hdd_remove_adapter( pHddCtx, pAdapterNode );
2380 vos_mem_free( pAdapterNode );
2381
Jeff Johnson295189b2012-06-20 16:38:30 -07002382
2383 /* If there is a single session of STA/P2P client, re-enable BMPS */
2384 if ((!vos_concurrent_sessions_running()) &&
2385 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
2386 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
2387 {
2388 hdd_enable_bmps_imps(pHddCtx);
2389 }
2390
2391 return VOS_STATUS_SUCCESS;
2392 }
2393
2394 return VOS_STATUS_E_FAILURE;
2395}
2396
2397VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
2398{
2399 hdd_adapter_list_node_t *pHddAdapterNode;
2400 VOS_STATUS status;
2401
2402 ENTER();
2403
2404 do
2405 {
2406 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
2407 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
2408 {
2409 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
2410 vos_mem_free( pHddAdapterNode );
2411 }
2412 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
2413
2414 EXIT();
2415
2416 return VOS_STATUS_SUCCESS;
2417}
2418
2419void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
2420{
2421 v_U8_t addIE[1] = {0};
2422
2423 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2424 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
2425 eANI_BOOLEAN_FALSE) )
2426 {
2427 hddLog(LOGE,
2428 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
2429 }
2430
2431 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2432 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
2433 eANI_BOOLEAN_FALSE) )
2434 {
2435 hddLog(LOGE,
2436 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
2437 }
2438
2439 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2440 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
2441 eANI_BOOLEAN_FALSE) )
2442 {
2443 hddLog(LOGE,
2444 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
2445 }
2446}
2447
2448VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2449{
2450 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2451 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2452 union iwreq_data wrqu;
2453
2454 ENTER();
2455
2456 switch(pAdapter->device_mode)
2457 {
2458 case WLAN_HDD_INFRA_STATION:
2459 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002460 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002461 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
2462 {
2463 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
2464 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
2465 pAdapter->sessionId,
2466 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
2467 else
2468 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
2469 pAdapter->sessionId,
2470 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2471 //success implies disconnect command got queued up successfully
2472 if(halStatus == eHAL_STATUS_SUCCESS)
2473 {
2474 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
2475 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2476 }
2477 memset(&wrqu, '\0', sizeof(wrqu));
2478 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2479 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2480 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2481 }
2482 else
2483 {
2484 hdd_abort_mac_scan(pHddCtx);
2485 }
2486
2487 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
2488 {
2489 INIT_COMPLETION(pAdapter->session_close_comp_var);
2490 if (eHAL_STATUS_SUCCESS ==
2491 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
2492 hdd_smeCloseSessionCallback, pAdapter))
2493 {
2494 //Block on a completion variable. Can't wait forever though.
2495 wait_for_completion_interruptible_timeout(
2496 &pAdapter->session_close_comp_var,
2497 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2498 }
2499 }
2500
2501 break;
2502
2503 case WLAN_HDD_SOFTAP:
2504 case WLAN_HDD_P2P_GO:
2505 //Any softap specific cleanup here...
2506 mutex_lock(&pHddCtx->sap_lock);
2507 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2508 {
2509 VOS_STATUS status;
2510 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2511
2512 //Stop Bss.
2513 status = WLANSAP_StopBss(pHddCtx->pvosContext);
2514 if (VOS_IS_STATUS_SUCCESS(status))
2515 {
2516 hdd_hostapd_state_t *pHostapdState =
2517 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2518
2519 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2520
2521 if (!VOS_IS_STATUS_SUCCESS(status))
2522 {
2523 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002524 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002525 }
2526 }
2527 else
2528 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002529 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002530 }
2531 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2532
2533 if (eHAL_STATUS_FAILURE ==
2534 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
2535 0, NULL, eANI_BOOLEAN_FALSE))
2536 {
2537 hddLog(LOGE,
2538 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002539 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002540 }
2541
2542 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2543 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2544 eANI_BOOLEAN_FALSE) )
2545 {
2546 hddLog(LOGE,
2547 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
2548 }
2549
2550 // Reset WNI_CFG_PROBE_RSP Flags
2551 wlan_hdd_reset_prob_rspies(pAdapter);
2552 kfree(pAdapter->sessionCtx.ap.beacon);
2553 pAdapter->sessionCtx.ap.beacon = NULL;
2554 }
2555 mutex_unlock(&pHddCtx->sap_lock);
2556 break;
2557 case WLAN_HDD_MONITOR:
2558 break;
2559 default:
2560 break;
2561 }
2562
2563 EXIT();
2564 return VOS_STATUS_SUCCESS;
2565}
2566
2567VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
2568{
2569 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2570 VOS_STATUS status;
2571 hdd_adapter_t *pAdapter;
2572
2573 ENTER();
2574
2575 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2576
2577 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2578 {
2579 pAdapter = pAdapterNode->pAdapter;
2580 netif_tx_disable(pAdapter->dev);
2581 netif_carrier_off(pAdapter->dev);
2582
2583 hdd_stop_adapter( pHddCtx, pAdapter );
2584
2585 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2586 pAdapterNode = pNext;
2587 }
2588
2589 EXIT();
2590
2591 return VOS_STATUS_SUCCESS;
2592}
2593
2594VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
2595{
2596 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2597 VOS_STATUS status;
2598 hdd_adapter_t *pAdapter;
2599
2600 ENTER();
2601
2602 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2603
2604 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2605 {
2606 pAdapter = pAdapterNode->pAdapter;
2607 netif_tx_disable(pAdapter->dev);
2608 netif_carrier_off(pAdapter->dev);
2609
2610 //Record whether STA is associated
2611 pAdapter->sessionCtx.station.bSendDisconnect =
2612 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
2613 VOS_TRUE : VOS_FALSE;
2614
2615 hdd_deinit_tx_rx(pAdapter);
2616 hdd_wmm_adapter_close(pAdapter);
2617
2618 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2619 pAdapterNode = pNext;
2620 }
2621
2622 EXIT();
2623
2624 return VOS_STATUS_SUCCESS;
2625}
2626
2627VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
2628{
2629 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2630 VOS_STATUS status;
2631 hdd_adapter_t *pAdapter;
2632 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
2633
2634 ENTER();
2635
2636 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2637
2638 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2639 {
2640 pAdapter = pAdapterNode->pAdapter;
2641
2642 switch(pAdapter->device_mode)
2643 {
2644 case WLAN_HDD_INFRA_STATION:
2645 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002646 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002647 hdd_init_station_mode(pAdapter);
2648 /* Open the gates for HDD to receive Wext commands */
2649 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002650 pHddCtx->scan_info.mScanPending = FALSE;
2651 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002652
2653 //Trigger the initial scan
2654 hdd_wlan_initial_scan(pAdapter);
2655
2656 //Indicate disconnect event to supplicant if associated previously
2657 if(pAdapter->sessionCtx.station.bSendDisconnect)
2658 {
2659 union iwreq_data wrqu;
2660 memset(&wrqu, '\0', sizeof(wrqu));
2661 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2662 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2663 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2664 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
2665
Jeff Johnson295189b2012-06-20 16:38:30 -07002666 /* indicate disconnected event to nl80211 */
2667 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
2668 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002669 }
2670 break;
2671
2672 case WLAN_HDD_SOFTAP:
2673 /* softAP can handle SSR */
2674 break;
2675
2676 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002677 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
2678 __func__);
2679 /* event supplicant to restart */
2680 cfg80211_del_sta(pAdapter->dev,
2681 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002682 break;
2683
2684 case WLAN_HDD_MONITOR:
2685 /* monitor interface start */
2686 break;
2687 default:
2688 break;
2689 }
2690
2691 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2692 pAdapterNode = pNext;
2693 }
2694
2695 EXIT();
2696
2697 return VOS_STATUS_SUCCESS;
2698}
2699
2700VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
2701{
2702 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2703 hdd_adapter_t *pAdapter;
2704 VOS_STATUS status;
2705 v_U32_t roamId;
2706
2707 ENTER();
2708
2709 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2710
2711 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2712 {
2713 pAdapter = pAdapterNode->pAdapter;
2714
2715 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
2716 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
2717 {
2718 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2719 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2720
2721 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2722 init_completion(&pAdapter->disconnect_comp_var);
2723 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
2724 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2725
2726 wait_for_completion_interruptible_timeout(
2727 &pAdapter->disconnect_comp_var,
2728 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2729
2730 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
2731 pHddCtx->isAmpAllowed = VOS_FALSE;
2732 sme_RoamConnect(pHddCtx->hHal,
2733 pAdapter->sessionId, &(pWextState->roamProfile),
2734 &roamId);
2735 }
2736
2737 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2738 pAdapterNode = pNext;
2739 }
2740
2741 EXIT();
2742
2743 return VOS_STATUS_SUCCESS;
2744}
2745
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002746bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07002747{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002748 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07002749}
2750
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002751/* Once SSR is disabled then it cannot be set. */
2752void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07002753{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002754 if (HDD_SSR_DISABLED == isSsrRequired)
2755 return;
2756
Jeff Johnson295189b2012-06-20 16:38:30 -07002757 isSsrRequired = value;
2758}
2759
2760VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
2761 hdd_adapter_list_node_t** ppAdapterNode)
2762{
2763 VOS_STATUS status;
2764 spin_lock(&pHddCtx->hddAdapters.lock);
2765 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
2766 (hdd_list_node_t**) ppAdapterNode );
2767 spin_unlock(&pHddCtx->hddAdapters.lock);
2768 return status;
2769}
2770
2771VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
2772 hdd_adapter_list_node_t* pAdapterNode,
2773 hdd_adapter_list_node_t** pNextAdapterNode)
2774{
2775 VOS_STATUS status;
2776 spin_lock(&pHddCtx->hddAdapters.lock);
2777 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
2778 (hdd_list_node_t*) pAdapterNode,
2779 (hdd_list_node_t**)pNextAdapterNode );
2780
2781 spin_unlock(&pHddCtx->hddAdapters.lock);
2782 return status;
2783}
2784
2785VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
2786 hdd_adapter_list_node_t* pAdapterNode)
2787{
2788 VOS_STATUS status;
2789 spin_lock(&pHddCtx->hddAdapters.lock);
2790 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
2791 &pAdapterNode->node );
2792 spin_unlock(&pHddCtx->hddAdapters.lock);
2793 return status;
2794}
2795
2796VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
2797 hdd_adapter_list_node_t** ppAdapterNode)
2798{
2799 VOS_STATUS status;
2800 spin_lock(&pHddCtx->hddAdapters.lock);
2801 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
2802 (hdd_list_node_t**) ppAdapterNode );
2803 spin_unlock(&pHddCtx->hddAdapters.lock);
2804 return status;
2805}
2806
2807VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
2808 hdd_adapter_list_node_t* pAdapterNode)
2809{
2810 VOS_STATUS status;
2811 spin_lock(&pHddCtx->hddAdapters.lock);
2812 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
2813 (hdd_list_node_t*) pAdapterNode );
2814 spin_unlock(&pHddCtx->hddAdapters.lock);
2815 return status;
2816}
2817
2818VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
2819 hdd_adapter_list_node_t* pAdapterNode)
2820{
2821 VOS_STATUS status;
2822 spin_lock(&pHddCtx->hddAdapters.lock);
2823 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
2824 (hdd_list_node_t*) pAdapterNode );
2825 spin_unlock(&pHddCtx->hddAdapters.lock);
2826 return status;
2827}
2828
2829hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
2830 tSirMacAddr macAddr )
2831{
2832 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2833 hdd_adapter_t *pAdapter;
2834 VOS_STATUS status;
2835
2836 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2837
2838 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2839 {
2840 pAdapter = pAdapterNode->pAdapter;
2841
2842 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
2843 macAddr, sizeof(tSirMacAddr) ) )
2844 {
2845 return pAdapter;
2846 }
2847 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2848 pAdapterNode = pNext;
2849 }
2850
2851 return NULL;
2852
2853}
2854
2855hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
2856{
2857 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2858 hdd_adapter_t *pAdapter;
2859 VOS_STATUS status;
2860
2861 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2862
2863 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2864 {
2865 pAdapter = pAdapterNode->pAdapter;
2866
2867 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
2868 IFNAMSIZ ) )
2869 {
2870 return pAdapter;
2871 }
2872 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2873 pAdapterNode = pNext;
2874 }
2875
2876 return NULL;
2877
2878}
2879
2880hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
2881{
2882 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2883 hdd_adapter_t *pAdapter;
2884 VOS_STATUS status;
2885
2886 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2887
2888 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2889 {
2890 pAdapter = pAdapterNode->pAdapter;
2891
2892 if( pAdapter && (mode == pAdapter->device_mode) )
2893 {
2894 return pAdapter;
2895 }
2896 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2897 pAdapterNode = pNext;
2898 }
2899
2900 return NULL;
2901
2902}
2903
2904//Remove this function later
2905hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
2906{
2907 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2908 hdd_adapter_t *pAdapter;
2909 VOS_STATUS status;
2910
2911 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2912
2913 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2914 {
2915 pAdapter = pAdapterNode->pAdapter;
2916
2917 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
2918 {
2919 return pAdapter;
2920 }
2921
2922 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2923 pAdapterNode = pNext;
2924 }
2925
2926 return NULL;
2927
2928}
2929
Jeff Johnson295189b2012-06-20 16:38:30 -07002930/**---------------------------------------------------------------------------
2931
2932 \brief hdd_set_monitor_tx_adapter() -
2933
2934 This API initializes the adapter to be used while transmitting on monitor
2935 adapter.
2936
2937 \param - pHddCtx - Pointer to the HDD context.
2938 pAdapter - Adapter that will used for TX. This can be NULL.
2939 \return - None.
2940 --------------------------------------------------------------------------*/
2941void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2942{
2943 hdd_adapter_t *pMonAdapter;
2944
2945 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
2946
2947 if( NULL != pMonAdapter )
2948 {
2949 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
2950 }
2951}
Jeff Johnson295189b2012-06-20 16:38:30 -07002952/**---------------------------------------------------------------------------
2953
2954 \brief hdd_select_queue() -
2955
2956 This API returns the operating channel of the requested device mode
2957
2958 \param - pHddCtx - Pointer to the HDD context.
2959 - mode - Device mode for which operating channel is required
2960 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
2961 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
2962 \return - channel number. "0" id the requested device is not found OR it is not connected.
2963 --------------------------------------------------------------------------*/
2964v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
2965{
2966 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2967 VOS_STATUS status;
2968 hdd_adapter_t *pAdapter;
2969 v_U8_t operatingChannel = 0;
2970
2971 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2972
2973 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2974 {
2975 pAdapter = pAdapterNode->pAdapter;
2976
2977 if( mode == pAdapter->device_mode )
2978 {
2979 switch(pAdapter->device_mode)
2980 {
2981 case WLAN_HDD_INFRA_STATION:
2982 case WLAN_HDD_P2P_CLIENT:
2983 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
2984 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
2985 break;
2986 case WLAN_HDD_SOFTAP:
2987 case WLAN_HDD_P2P_GO:
2988 /*softap connection info */
2989 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2990 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
2991 break;
2992 default:
2993 break;
2994 }
2995
2996 break; //Found the device of interest. break the loop
2997 }
2998
2999 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3000 pAdapterNode = pNext;
3001 }
3002 return operatingChannel;
3003}
3004
3005#ifdef WLAN_FEATURE_PACKET_FILTERING
3006/**---------------------------------------------------------------------------
3007
3008 \brief hdd_set_multicast_list() -
3009
3010 This used to set the multicast address list.
3011
3012 \param - dev - Pointer to the WLAN device.
3013 - skb - Pointer to OS packet (sk_buff).
3014 \return - success/fail
3015
3016 --------------------------------------------------------------------------*/
3017static void hdd_set_multicast_list(struct net_device *dev)
3018{
3019 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07003020 int mc_count;
3021 int i = 0;
3022 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303023
3024 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07003025 {
3026 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303027 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003028 return;
3029 }
3030
3031 if (dev->flags & IFF_ALLMULTI)
3032 {
3033 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003034 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303035 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003036 }
3037 else
3038 {
3039 mc_count = netdev_mc_count(dev);
3040 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003041 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07003042 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
3043 {
3044 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003045 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303046 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003047 return;
3048 }
3049
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303050 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07003051
3052 netdev_for_each_mc_addr(ha, dev) {
3053 if (i == mc_count)
3054 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303055 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
3056 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
3057 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003058 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303059 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07003060 i++;
3061 }
3062 }
3063 return;
3064}
3065#endif
3066
3067/**---------------------------------------------------------------------------
3068
3069 \brief hdd_select_queue() -
3070
3071 This function is registered with the Linux OS for network
3072 core to decide which queue to use first.
3073
3074 \param - dev - Pointer to the WLAN device.
3075 - skb - Pointer to OS packet (sk_buff).
3076 \return - ac, Queue Index/access category corresponding to UP in IP header
3077
3078 --------------------------------------------------------------------------*/
3079v_U16_t hdd_select_queue(struct net_device *dev,
3080 struct sk_buff *skb)
3081{
3082 return hdd_wmm_select_queue(dev, skb);
3083}
3084
3085
3086/**---------------------------------------------------------------------------
3087
3088 \brief hdd_wlan_initial_scan() -
3089
3090 This function triggers the initial scan
3091
3092 \param - pAdapter - Pointer to the HDD adapter.
3093
3094 --------------------------------------------------------------------------*/
3095void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
3096{
3097 tCsrScanRequest scanReq;
3098 tCsrChannelInfo channelInfo;
3099 eHalStatus halStatus;
3100 unsigned long scanId;
3101 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3102
3103 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
3104 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
3105 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
3106
3107 if(sme_Is11dSupported(pHddCtx->hHal))
3108 {
3109 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
3110 if ( HAL_STATUS_SUCCESS( halStatus ) )
3111 {
3112 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
3113 if( !scanReq.ChannelInfo.ChannelList )
3114 {
3115 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
3116 vos_mem_free(channelInfo.ChannelList);
3117 return;
3118 }
3119 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
3120 channelInfo.numOfChannels);
3121 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
3122 vos_mem_free(channelInfo.ChannelList);
3123 }
3124
3125 scanReq.scanType = eSIR_PASSIVE_SCAN;
3126 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
3127 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
3128 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
3129 }
3130 else
3131 {
3132 scanReq.scanType = eSIR_ACTIVE_SCAN;
3133 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
3134 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
3135 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
3136 }
3137
3138 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
3139 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3140 {
3141 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
3142 __func__, halStatus );
3143 }
3144
3145 if(sme_Is11dSupported(pHddCtx->hHal))
3146 vos_mem_free(scanReq.ChannelInfo.ChannelList);
3147}
3148
3149struct fullPowerContext
3150{
3151 struct completion completion;
3152 unsigned int magic;
3153};
3154#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
3155
3156/**---------------------------------------------------------------------------
3157
3158 \brief hdd_full_power_callback() - HDD full power callback function
3159
3160 This is the function invoked by SME to inform the result of a full power
3161 request issued by HDD
3162
3163 \param - callbackcontext - Pointer to cookie
3164 \param - status - result of request
3165
3166 \return - None
3167
3168 --------------------------------------------------------------------------*/
3169static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
3170{
3171 struct fullPowerContext *pContext = callbackContext;
3172
3173 hddLog(VOS_TRACE_LEVEL_INFO,
3174 "%s: context = %p, status = %d", pContext, status);
3175
3176 if (NULL == callbackContext)
3177 {
3178 hddLog(VOS_TRACE_LEVEL_ERROR,
3179 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003180 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07003181 return;
3182 }
3183
3184 /* there is a race condition that exists between this callback function
3185 and the caller since the caller could time out either before or
3186 while this code is executing. we'll assume the timeout hasn't
3187 occurred, but we'll verify that right before we save our work */
3188
3189 if (POWER_CONTEXT_MAGIC != pContext->magic)
3190 {
3191 /* the caller presumably timed out so there is nothing we can do */
3192 hddLog(VOS_TRACE_LEVEL_WARN,
3193 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003194 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07003195 return;
3196 }
3197
3198 /* the race is on. caller could have timed out immediately after
3199 we verified the magic, but if so, caller will wait a short time
3200 for us to notify the caller, so the context will stay valid */
3201 complete(&pContext->completion);
3202}
3203
3204/**---------------------------------------------------------------------------
3205
3206 \brief hdd_wlan_exit() - HDD WLAN exit function
3207
3208 This is the driver exit point (invoked during rmmod)
3209
3210 \param - pHddCtx - Pointer to the HDD Context
3211
3212 \return - None
3213
3214 --------------------------------------------------------------------------*/
3215void hdd_wlan_exit(hdd_context_t *pHddCtx)
3216{
3217 eHalStatus halStatus;
3218 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
3219 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05303220 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003221 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003222 struct fullPowerContext powerContext;
3223 long lrc;
3224
3225 ENTER();
3226
Jeff Johnson88ba7742013-02-27 14:36:02 -08003227 if (VOS_FTM_MODE != hdd_get_conparam())
3228 {
3229 // Unloading, restart logic is no more required.
3230 wlan_hdd_restart_deinit(pHddCtx);
3231 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003232
Jeff Johnson295189b2012-06-20 16:38:30 -07003233 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003234 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003235 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003236 {
3237 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
3238 WLAN_HDD_INFRA_STATION);
3239 if (pAdapter == NULL)
3240 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3241
3242 if (pAdapter != NULL)
3243 {
3244 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
3245 hdd_UnregisterWext(pAdapter->dev);
3246 }
3247 }
3248 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003249
Jeff Johnson295189b2012-06-20 16:38:30 -07003250 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08003251 {
3252 wlan_hdd_ftm_close(pHddCtx);
3253 goto free_hdd_ctx;
3254 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003255 //Stop the Interface TX queue.
3256 //netif_tx_disable(pWlanDev);
3257 //netif_carrier_off(pWlanDev);
3258
Jeff Johnson295189b2012-06-20 16:38:30 -07003259 if (VOS_STA_SAP_MODE == hdd_get_conparam())
3260 {
3261 pAdapter = hdd_get_adapter(pHddCtx,
3262 WLAN_HDD_SOFTAP);
3263 }
3264 else
3265 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003266 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003267 {
3268 pAdapter = hdd_get_adapter(pHddCtx,
3269 WLAN_HDD_INFRA_STATION);
3270 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003271 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003272 /* DeRegister with platform driver as client for Suspend/Resume */
3273 vosStatus = hddDeregisterPmOps(pHddCtx);
3274 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3275 {
3276 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
3277 VOS_ASSERT(0);
3278 }
3279
3280 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
3281 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3282 {
3283 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
3284 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003285
Chilam NG571c65a2013-01-19 12:27:36 +05303286#ifdef FEATURE_WLAN_TDLS
3287 wlan_hdd_tdls_exit();
3288#endif
3289
Jeff Johnson295189b2012-06-20 16:38:30 -07003290 // Cancel any outstanding scan requests. We are about to close all
3291 // of our adapters, but an adapter structure is what SME passes back
3292 // to our callback function. Hence if there are any outstanding scan
3293 // requests then there is a race condition between when the adapter
3294 // is closed and when the callback is invoked. We try to resolve that
3295 // race condition here by canceling any outstanding scans before we
3296 // close the adapters.
3297 // Note that the scans may be cancelled in an asynchronous manner, so
3298 // ideally there needs to be some kind of synchronization. Rather than
3299 // introduce a new synchronization here, we will utilize the fact that
3300 // we are about to Request Full Power, and since that is synchronized,
3301 // the expectation is that by the time Request Full Power has completed,
3302 // all scans will be cancelled.
3303 hdd_abort_mac_scan( pHddCtx );
3304
3305 //Disable IMPS/BMPS as we do not want the device to enter any power
3306 //save mode during shutdown
3307 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3308 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3309 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
3310
3311 //Ensure that device is in full power as we will touch H/W during vos_Stop
3312 init_completion(&powerContext.completion);
3313 powerContext.magic = POWER_CONTEXT_MAGIC;
3314
3315 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
3316 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
3317
3318 if (eHAL_STATUS_SUCCESS != halStatus)
3319 {
3320 if (eHAL_STATUS_PMC_PENDING == halStatus)
3321 {
3322 /* request was sent -- wait for the response */
3323 lrc = wait_for_completion_interruptible_timeout(
3324 &powerContext.completion,
3325 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
3326 /* either we have a response or we timed out
3327 either way, first invalidate our magic */
3328 powerContext.magic = 0;
3329 if (lrc <= 0)
3330 {
3331 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003332 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07003333 /* there is a race condition such that the callback
3334 function could be executing at the same time we are. of
3335 primary concern is if the callback function had already
3336 verified the "magic" but hasn't yet set the completion
3337 variable. Since the completion variable is on our
3338 stack, we'll delay just a bit to make sure the data is
3339 still valid if that is the case */
3340 msleep(50);
3341 }
3342 }
3343 else
3344 {
3345 hddLog(VOS_TRACE_LEVEL_ERROR,
3346 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003347 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07003348 VOS_ASSERT(0);
3349 /* continue -- need to clean up as much as possible */
3350 }
3351 }
3352
3353 // Unregister the Net Device Notifier
3354 unregister_netdevice_notifier(&hdd_netdev_notifier);
3355
Jeff Johnson295189b2012-06-20 16:38:30 -07003356 hdd_stop_all_adapters( pHddCtx );
3357
Jeff Johnson295189b2012-06-20 16:38:30 -07003358#ifdef WLAN_BTAMP_FEATURE
3359 vosStatus = WLANBAP_Stop(pVosContext);
3360 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3361 {
3362 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3363 "%s: Failed to stop BAP",__func__);
3364 }
3365#endif //WLAN_BTAMP_FEATURE
3366
3367 //Stop all the modules
3368 vosStatus = vos_stop( pVosContext );
3369 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3370 {
3371 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3372 "%s: Failed to stop VOSS",__func__);
3373 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3374 }
3375
Jeff Johnson295189b2012-06-20 16:38:30 -07003376 //Assert Deep sleep signal now to put Libra HW in lowest power state
3377 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
3378 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3379
3380 //Vote off any PMIC voltage supplies
3381 vos_chipPowerDown(NULL, NULL, NULL);
3382
3383 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
3384
3385 //Clean up HDD Nlink Service
3386 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
3387 nl_srv_exit();
3388
3389 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07003390 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003391
3392 //Close the scheduler before calling vos_close to make sure no thread is
3393 // scheduled after the each module close is called i.e after all the data
3394 // structures are freed.
3395 vosStatus = vos_sched_close( pVosContext );
3396 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
3397 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
3398 "%s: Failed to close VOSS Scheduler",__func__);
3399 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3400 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003401#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07003402#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3403 /* Destroy the wake lock */
3404 wake_lock_destroy(&pHddCtx->rx_wake_lock);
3405#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08003406 /* Destroy the wake lock */
3407 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003408#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003409
3410 //Close VOSS
3411 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
3412 vos_close(pVosContext);
3413
Jeff Johnson295189b2012-06-20 16:38:30 -07003414 //Close Watchdog
3415 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3416 vos_watchdog_close(pVosContext);
3417
3418 /* Cancel the vote for XO Core ON.
3419 * This is done here to ensure there is no race condition since MC, TX and WD threads have
3420 * exited at this point
3421 */
3422 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
3423 " when WLAN is turned OFF\n");
3424 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
3425 {
3426 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
3427 " Not returning failure."
3428 " Power consumed will be high\n");
3429 }
3430
3431 hdd_close_all_adapters( pHddCtx );
3432
3433
3434 //Free up dynamically allocated members inside HDD Adapter
3435 kfree(pHddCtx->cfg_ini);
3436 pHddCtx->cfg_ini= NULL;
3437
3438 /* free the power on lock from platform driver */
3439 if (free_riva_power_on_lock("wlan"))
3440 {
3441 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
3442 __func__);
3443 }
3444
Jeff Johnson88ba7742013-02-27 14:36:02 -08003445free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08003446 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07003447 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07003448 if (hdd_is_ssr_required())
3449 {
3450 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07003451 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07003452 msleep(5000);
3453 }
3454 hdd_set_ssr_required (VOS_FALSE);
3455}
3456
3457
3458/**---------------------------------------------------------------------------
3459
3460 \brief hdd_update_config_from_nv() - Function to update the contents of
3461 the running configuration with parameters taken from NV storage
3462
3463 \param - pHddCtx - Pointer to the HDD global context
3464
3465 \return - VOS_STATUS_SUCCESS if successful
3466
3467 --------------------------------------------------------------------------*/
3468static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
3469{
Jeff Johnson295189b2012-06-20 16:38:30 -07003470 v_BOOL_t itemIsValid = VOS_FALSE;
3471 VOS_STATUS status;
3472 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
3473 v_U8_t macLoop;
3474
3475 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
3476 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
3477 if(status != VOS_STATUS_SUCCESS)
3478 {
3479 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
3480 return VOS_STATUS_E_FAILURE;
3481 }
3482
3483 if (itemIsValid == VOS_TRUE)
3484 {
3485 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
3486 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
3487 VOS_MAX_CONCURRENCY_PERSONA);
3488 if(status != VOS_STATUS_SUCCESS)
3489 {
3490 /* Get MAC from NV fail, not update CFG info
3491 * INI MAC value will be used for MAC setting */
3492 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
3493 return VOS_STATUS_E_FAILURE;
3494 }
3495
3496 /* If first MAC is not valid, treat all others are not valid
3497 * Then all MACs will be got from ini file */
3498 if(vos_is_macaddr_zero(&macFromNV[0]))
3499 {
3500 /* MAC address in NV file is not configured yet */
3501 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
3502 return VOS_STATUS_E_INVAL;
3503 }
3504
3505 /* Get MAC address from NV, update CFG info */
3506 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
3507 {
3508 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
3509 {
3510 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
3511 /* This MAC is not valid, skip it
3512 * This MAC will be got from ini file */
3513 }
3514 else
3515 {
3516 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
3517 (v_U8_t *)&macFromNV[macLoop].bytes[0],
3518 VOS_MAC_ADDR_SIZE);
3519 }
3520 }
3521 }
3522 else
3523 {
3524 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
3525 return VOS_STATUS_E_FAILURE;
3526 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003527
Jeff Johnson295189b2012-06-20 16:38:30 -07003528
3529 return VOS_STATUS_SUCCESS;
3530}
3531
3532/**---------------------------------------------------------------------------
3533
3534 \brief hdd_post_voss_start_config() - HDD post voss start config helper
3535
3536 \param - pAdapter - Pointer to the HDD
3537
3538 \return - None
3539
3540 --------------------------------------------------------------------------*/
3541VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
3542{
3543 eHalStatus halStatus;
3544 v_U32_t listenInterval;
3545
Jeff Johnson295189b2012-06-20 16:38:30 -07003546
3547 // Send ready indication to the HDD. This will kick off the MAC
3548 // into a 'running' state and should kick off an initial scan.
3549 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
3550 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3551 {
3552 hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
3553 "code %08d [x%08x]",__func__, halStatus, halStatus );
3554 return VOS_STATUS_E_FAILURE;
3555 }
3556
3557 // Set default LI into HDD context,
3558 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
3559 // And RIVA will crash
3560 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
3561 pHddCtx->hdd_actual_LI_value = listenInterval;
3562
3563 return VOS_STATUS_SUCCESS;
3564}
3565
Jeff Johnson295189b2012-06-20 16:38:30 -07003566/* wake lock APIs for HDD */
3567void hdd_prevent_suspend(void)
3568{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003569#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003570 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003571#else
3572 wcnss_prevent_suspend();
3573#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003574}
3575
3576void hdd_allow_suspend(void)
3577{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003578#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003579 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003580#else
3581 wcnss_allow_suspend();
3582#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003583}
3584
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003585void hdd_allow_suspend_timeout(v_U32_t timeout)
3586{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003587#ifdef WLAN_OPEN_SOURCE
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003588 wake_lock_timeout(&wlan_wake_lock, timeout);
3589#else
3590 /* Do nothing as there is no API in wcnss for timeout*/
3591#endif
3592}
3593
Jeff Johnson295189b2012-06-20 16:38:30 -07003594/**---------------------------------------------------------------------------
3595
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003596 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
3597 information between Host and Riva
3598
3599 This function gets reported version of FW
3600 It also finds the version of Riva headers used to compile the host
3601 It compares the above two and prints a warning if they are different
3602 It gets the SW and HW version string
3603 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
3604 indicating the features they support through a bitmap
3605
3606 \param - pHddCtx - Pointer to HDD context
3607
3608 \return - void
3609
3610 --------------------------------------------------------------------------*/
3611
3612void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
3613{
3614
3615 tSirVersionType versionCompiled;
3616 tSirVersionType versionReported;
3617 tSirVersionString versionString;
3618 tANI_U8 fwFeatCapsMsgSupported = 0;
3619 VOS_STATUS vstatus;
3620
3621 /* retrieve and display WCNSS version information */
3622 do {
3623
3624 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
3625 &versionCompiled);
3626 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3627 {
3628 hddLog(VOS_TRACE_LEVEL_FATAL,
3629 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003630 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003631 break;
3632 }
3633
3634 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
3635 &versionReported);
3636 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3637 {
3638 hddLog(VOS_TRACE_LEVEL_FATAL,
3639 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003640 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003641 break;
3642 }
3643
3644 if ((versionCompiled.major != versionReported.major) ||
3645 (versionCompiled.minor != versionReported.minor) ||
3646 (versionCompiled.version != versionReported.version) ||
3647 (versionCompiled.revision != versionReported.revision))
3648 {
3649 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
3650 "Host expected %u.%u.%u.%u\n",
3651 WLAN_MODULE_NAME,
3652 (int)versionReported.major,
3653 (int)versionReported.minor,
3654 (int)versionReported.version,
3655 (int)versionReported.revision,
3656 (int)versionCompiled.major,
3657 (int)versionCompiled.minor,
3658 (int)versionCompiled.version,
3659 (int)versionCompiled.revision);
3660 }
3661 else
3662 {
3663 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
3664 WLAN_MODULE_NAME,
3665 (int)versionReported.major,
3666 (int)versionReported.minor,
3667 (int)versionReported.version,
3668 (int)versionReported.revision);
3669 }
3670
3671 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
3672 versionString,
3673 sizeof(versionString));
3674 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3675 {
3676 hddLog(VOS_TRACE_LEVEL_FATAL,
3677 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003678 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003679 break;
3680 }
3681
3682 pr_info("%s: WCNSS software version %s\n",
3683 WLAN_MODULE_NAME, versionString);
3684
3685 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
3686 versionString,
3687 sizeof(versionString));
3688 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3689 {
3690 hddLog(VOS_TRACE_LEVEL_FATAL,
3691 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003692 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003693 break;
3694 }
3695
3696 pr_info("%s: WCNSS hardware version %s\n",
3697 WLAN_MODULE_NAME, versionString);
3698
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003699 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
3700 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003701 send the message only if it the riva is 1.1
3702 minor numbers for different riva branches:
3703 0 -> (1.0)Mainline Build
3704 1 -> (1.1)Mainline Build
3705 2->(1.04) Stability Build
3706 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003707 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003708 ((versionReported.minor>=1) && (versionReported.version>=1)))
3709 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
3710 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003711
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003712 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08003713 {
3714#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
3715 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
3716 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
3717#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003718 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08003719 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003720
3721 } while (0);
3722
3723}
3724
3725/**---------------------------------------------------------------------------
3726
Jeff Johnson295189b2012-06-20 16:38:30 -07003727 \brief hdd_wlan_startup() - HDD init function
3728
3729 This is the driver startup code executed once a WLAN device has been detected
3730
3731 \param - dev - Pointer to the underlying device
3732
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003733 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07003734
3735 --------------------------------------------------------------------------*/
3736
3737int hdd_wlan_startup(struct device *dev )
3738{
3739 VOS_STATUS status;
3740 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003741 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003742 hdd_context_t *pHddCtx = NULL;
3743 v_CONTEXT_t pVosContext= NULL;
3744#ifdef WLAN_BTAMP_FEATURE
3745 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
3746 WLANBAP_ConfigType btAmpConfig;
3747 hdd_config_t *pConfig;
3748#endif
3749 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07003750 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003751
3752 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07003753 /*
3754 * cfg80211: wiphy allocation
3755 */
3756 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
3757
3758 if(wiphy == NULL)
3759 {
3760 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003761 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003762 }
3763
3764 pHddCtx = wiphy_priv(wiphy);
3765
Jeff Johnson295189b2012-06-20 16:38:30 -07003766 //Initialize the adapter context to zeros.
3767 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
3768
Jeff Johnson295189b2012-06-20 16:38:30 -07003769 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003770 hdd_prevent_suspend();
3771 pHddCtx->isLoadUnloadInProgress = TRUE;
3772
3773 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
3774
3775 /*Get vos context here bcoz vos_open requires it*/
3776 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
3777
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08003778 if(pVosContext == NULL)
3779 {
3780 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
3781 goto err_free_hdd_context;
3782 }
3783
Jeff Johnson295189b2012-06-20 16:38:30 -07003784 //Save the Global VOSS context in adapter context for future.
3785 pHddCtx->pvosContext = pVosContext;
3786
3787 //Save the adapter context in global context for future.
3788 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
3789
Jeff Johnson295189b2012-06-20 16:38:30 -07003790 pHddCtx->parent_dev = dev;
3791
3792 init_completion(&pHddCtx->full_pwr_comp_var);
3793 init_completion(&pHddCtx->standby_comp_var);
3794 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003795 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003796 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003797
3798 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
3799
3800 // Load all config first as TL config is needed during vos_open
3801 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
3802 if(pHddCtx->cfg_ini == NULL)
3803 {
3804 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
3805 goto err_free_hdd_context;
3806 }
3807
3808 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
3809
3810 // Read and parse the qcom_cfg.ini file
3811 status = hdd_parse_config_ini( pHddCtx );
3812 if ( VOS_STATUS_SUCCESS != status )
3813 {
3814 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
3815 __func__, WLAN_INI_FILE);
3816 goto err_config;
3817 }
3818
Jeff Johnson295189b2012-06-20 16:38:30 -07003819 /*
3820 * cfg80211: Initialization and registration ...
3821 */
3822 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
3823 {
3824 hddLog(VOS_TRACE_LEVEL_FATAL,
3825 "%s: wlan_hdd_cfg80211_register return failure", __func__);
3826 goto err_wiphy_reg;
3827 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003828
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003829 // Update VOS trace levels based upon the cfg.ini
3830 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
3831 pHddCtx->cfg_ini->vosTraceEnableBAP);
3832 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
3833 pHddCtx->cfg_ini->vosTraceEnableTL);
3834 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
3835 pHddCtx->cfg_ini->vosTraceEnableWDI);
3836 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
3837 pHddCtx->cfg_ini->vosTraceEnableHDD);
3838 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
3839 pHddCtx->cfg_ini->vosTraceEnableSME);
3840 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
3841 pHddCtx->cfg_ini->vosTraceEnablePE);
3842 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
3843 pHddCtx->cfg_ini->vosTraceEnableWDA);
3844 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
3845 pHddCtx->cfg_ini->vosTraceEnableSYS);
3846 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
3847 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003848 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
3849 pHddCtx->cfg_ini->vosTraceEnableSAP);
3850 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
3851 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003852
Jeff Johnson295189b2012-06-20 16:38:30 -07003853 // Update WDI trace levels based upon the cfg.ini
3854 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
3855 pHddCtx->cfg_ini->wdiTraceEnableDAL);
3856 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
3857 pHddCtx->cfg_ini->wdiTraceEnableCTL);
3858 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
3859 pHddCtx->cfg_ini->wdiTraceEnableDAT);
3860 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
3861 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003862
Jeff Johnson88ba7742013-02-27 14:36:02 -08003863 if (VOS_FTM_MODE == hdd_get_conparam())
3864 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003865 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
3866 {
3867 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
3868 goto err_free_hdd_context;
3869 }
3870 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
3871 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08003872 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003873
Jeff Johnson88ba7742013-02-27 14:36:02 -08003874 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07003875 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3876 {
3877 status = vos_watchdog_open(pVosContext,
3878 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
3879
3880 if(!VOS_IS_STATUS_SUCCESS( status ))
3881 {
3882 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003883 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07003884 }
3885 }
3886
3887 pHddCtx->isLogpInProgress = FALSE;
3888 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
3889
Jeff Johnson295189b2012-06-20 16:38:30 -07003890 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
3891 if(!VOS_IS_STATUS_SUCCESS(status))
3892 {
3893 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003894 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07003895 }
3896
Jeff Johnson295189b2012-06-20 16:38:30 -07003897 status = vos_open( &pVosContext, 0);
3898 if ( !VOS_IS_STATUS_SUCCESS( status ))
3899 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003900 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
3901 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07003902 }
3903
Jeff Johnson295189b2012-06-20 16:38:30 -07003904 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
3905
3906 if ( NULL == pHddCtx->hHal )
3907 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003908 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003909 goto err_vosclose;
3910 }
3911
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003912 status = vos_preStart( pHddCtx->pvosContext );
3913 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3914 {
3915 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
3916 goto err_vosclose;
3917 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003918
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003919 /* Note that the vos_preStart() sequence triggers the cfg download.
3920 The cfg download must occur before we update the SME config
3921 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07003922 status = hdd_set_sme_config( pHddCtx );
3923
3924 if ( VOS_STATUS_SUCCESS != status )
3925 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003926 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
3927 goto err_vosclose;
3928 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003929
3930 //Initialize the WMM module
3931 status = hdd_wmm_init(pHddCtx);
3932 if (!VOS_IS_STATUS_SUCCESS(status))
3933 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003934 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003935 goto err_vosclose;
3936 }
3937
Jeff Johnson295189b2012-06-20 16:38:30 -07003938 /* In the integrated architecture we update the configuration from
3939 the INI file and from NV before vOSS has been started so that
3940 the final contents are available to send down to the cCPU */
3941
3942 // Apply the cfg.ini to cfg.dat
3943 if (FALSE == hdd_update_config_dat(pHddCtx))
3944 {
3945 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
3946 goto err_vosclose;
3947 }
3948
3949 // Apply the NV to cfg.dat
3950 /* Prima Update MAC address only at here */
3951 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
3952 {
3953#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
3954 /* There was not a valid set of MAC Addresses in NV. See if the
3955 default addresses were modified by the cfg.ini settings. If so,
3956 we'll use them, but if not, we'll autogenerate a set of MAC
3957 addresses based upon the device serial number */
3958
3959 static const v_MACADDR_t default_address =
3960 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
3961 unsigned int serialno;
3962 int i;
3963
3964 serialno = wcnss_get_serial_number();
3965 if ((0 != serialno) &&
3966 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
3967 sizeof(default_address))))
3968 {
3969 /* cfg.ini has the default address, invoke autogen logic */
3970
3971 /* MAC address has 3 bytes of OUI so we have a maximum of 3
3972 bytes of the serial number that can be used to generate
3973 the other 3 bytes of the MAC address. Mask off all but
3974 the lower 3 bytes (this will also make sure we don't
3975 overflow in the next step) */
3976 serialno &= 0x00FFFFFF;
3977
3978 /* we need a unique address for each session */
3979 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
3980
3981 /* autogen all addresses */
3982 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3983 {
3984 /* start with the entire default address */
3985 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
3986 /* then replace the lower 3 bytes */
3987 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
3988 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
3989 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
3990
3991 serialno++;
3992 }
3993
3994 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
3995 MAC_ADDRESS_STR,
3996 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
3997 }
3998 else
3999#endif //WLAN_AUTOGEN_MACADDR_FEATURE
4000 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004001 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004002 "%s: Invalid MAC address in NV, using MAC from ini file "
4003 MAC_ADDRESS_STR, __func__,
4004 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4005 }
4006 }
4007 {
4008 eHalStatus halStatus;
4009 // Set the MAC Address
4010 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
4011 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
4012 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
4013 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
4014
4015 if (!HAL_STATUS_SUCCESS( halStatus ))
4016 {
4017 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
4018 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08004019 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004020 }
4021 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004022
4023 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
4024 Note: Firmware image will be read and downloaded inside vos_start API */
4025 status = vos_start( pHddCtx->pvosContext );
4026 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4027 {
4028 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
4029 goto err_vosclose;
4030 }
4031
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004032 /* Exchange capability info between Host and FW and also get versioning info from FW */
4033 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004034
4035 status = hdd_post_voss_start_config( pHddCtx );
4036 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4037 {
4038 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
4039 __func__);
4040 goto err_vosstop;
4041 }
4042
Jeff Johnson295189b2012-06-20 16:38:30 -07004043 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4044 {
4045 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
4046 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4047 }
4048 else
4049 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004050 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
4051 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4052 if (pAdapter != NULL)
4053 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304054 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07004055 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304056 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
4057 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
4058 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07004059
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304060 /* Generate the P2P Device Address. This consists of the device's
4061 * primary MAC address with the locally administered bit set.
4062 */
4063 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07004064 }
4065 else
4066 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304067 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
4068 if (p2p_dev_addr != NULL)
4069 {
4070 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
4071 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
4072 }
4073 else
4074 {
4075 hddLog(VOS_TRACE_LEVEL_FATAL,
4076 "%s: Failed to allocate mac_address for p2p_device",
4077 __func__);
4078 goto err_close_adapter;
4079 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004080 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004081
4082 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
4083 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
4084 if ( NULL == pP2pAdapter )
4085 {
4086 hddLog(VOS_TRACE_LEVEL_FATAL,
4087 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004088 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004089 goto err_close_adapter;
4090 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004091 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004092 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004093
4094 if( pAdapter == NULL )
4095 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004096 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
4097 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004098 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004099
Jeff Johnson295189b2012-06-20 16:38:30 -07004100#ifdef WLAN_BTAMP_FEATURE
4101 vStatus = WLANBAP_Open(pVosContext);
4102 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4103 {
4104 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4105 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004106 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004107 }
4108
4109 vStatus = BSL_Init(pVosContext);
4110 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4111 {
4112 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4113 "%s: Failed to Init BSL",__func__);
4114 goto err_bap_close;
4115 }
4116 vStatus = WLANBAP_Start(pVosContext);
4117 if (!VOS_IS_STATUS_SUCCESS(vStatus))
4118 {
4119 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4120 "%s: Failed to start TL",__func__);
4121 goto err_bap_close;
4122 }
4123
4124 pConfig = pHddCtx->cfg_ini;
4125 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
4126 status = WLANBAP_SetConfig(&btAmpConfig);
4127
4128#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07004129
Jeff Johnson295189b2012-06-20 16:38:30 -07004130#ifdef FEATURE_WLAN_SCAN_PNO
4131 /*SME must send channel update configuration to RIVA*/
4132 sme_UpdateChannelConfig(pHddCtx->hHal);
4133#endif
4134
Jeff Johnson295189b2012-06-20 16:38:30 -07004135 /* Register with platform driver as client for Suspend/Resume */
4136 status = hddRegisterPmOps(pHddCtx);
4137 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4138 {
4139 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
4140#ifdef WLAN_BTAMP_FEATURE
4141 goto err_bap_stop;
4142#else
Jeff Johnsone7245742012-09-05 17:12:55 -07004143 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004144#endif //WLAN_BTAMP_FEATURE
4145 }
4146
4147 /* Register TM level change handler function to the platform */
4148 status = hddDevTmRegisterNotifyCallback(pHddCtx);
4149 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4150 {
4151 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
4152 goto err_unregister_pmops;
4153 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004154
4155 /* register for riva power on lock to platform driver */
4156 if (req_riva_power_on_lock("wlan"))
4157 {
4158 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
4159 __func__);
4160 goto err_unregister_pmops;
4161 }
4162
Jeff Johnson295189b2012-06-20 16:38:30 -07004163 // register net device notifier for device change notification
4164 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4165
4166 if(ret < 0)
4167 {
4168 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
4169 goto err_free_power_on_lock;
4170 }
4171
4172 //Initialize the nlink service
4173 if(nl_srv_init() != 0)
4174 {
4175 hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
4176 goto err_reg_netdev;
4177 }
4178
4179 //Initialize the BTC service
4180 if(btc_activate_service(pHddCtx) != 0)
4181 {
4182 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
4183 goto err_nl_srv;
4184 }
4185
4186#ifdef PTT_SOCK_SVC_ENABLE
4187 //Initialize the PTT service
4188 if(ptt_sock_activate_svc(pHddCtx) != 0)
4189 {
4190 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
4191 goto err_nl_srv;
4192 }
4193#endif
4194
Jeff Johnson295189b2012-06-20 16:38:30 -07004195 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004196 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004197 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07004198 /* Action frame registered in one adapter which will
4199 * applicable to all interfaces
4200 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07004201 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07004202 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004203
4204 mutex_init(&pHddCtx->sap_lock);
4205
4206 pHddCtx->isLoadUnloadInProgress = FALSE;
4207
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004208#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004209#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4210 /* Initialize the wake lcok */
4211 wake_lock_init(&pHddCtx->rx_wake_lock,
4212 WAKE_LOCK_SUSPEND,
4213 "qcom_rx_wakelock");
4214#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004215 /* Initialize the wake lcok */
4216 wake_lock_init(&pHddCtx->sap_wake_lock,
4217 WAKE_LOCK_SUSPEND,
4218 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004219#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004220
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004221 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
4222 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07004223
4224 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4225 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004226
4227 // Initialize the restart logic
4228 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05304229
4230#ifdef FEATURE_WLAN_TDLS
Hoonki Lee387663d2013-02-05 18:08:43 -08004231 if(0 != wlan_hdd_tdls_init(pAdapter->dev))
4232 {
4233 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_tdls_init failed",__func__);
4234 goto err_nl_srv;
4235 }
Chilam NG571c65a2013-01-19 12:27:36 +05304236#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004237
4238 goto success;
4239
4240err_nl_srv:
4241 nl_srv_exit();
4242
4243err_reg_netdev:
4244 unregister_netdevice_notifier(&hdd_netdev_notifier);
4245
4246err_free_power_on_lock:
4247 free_riva_power_on_lock("wlan");
4248
4249err_unregister_pmops:
4250 hddDevTmUnregisterNotifyCallback(pHddCtx);
4251 hddDeregisterPmOps(pHddCtx);
4252
4253#ifdef WLAN_BTAMP_FEATURE
4254err_bap_stop:
4255 WLANBAP_Stop(pVosContext);
4256#endif
4257
4258#ifdef WLAN_BTAMP_FEATURE
4259err_bap_close:
4260 WLANBAP_Close(pVosContext);
4261#endif
4262
Jeff Johnson295189b2012-06-20 16:38:30 -07004263err_close_adapter:
4264 hdd_close_all_adapters( pHddCtx );
4265
4266err_vosstop:
4267 vos_stop(pVosContext);
4268
4269err_vosclose:
4270 status = vos_sched_close( pVosContext );
4271 if (!VOS_IS_STATUS_SUCCESS(status)) {
4272 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4273 "%s: Failed to close VOSS Scheduler", __func__);
4274 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
4275 }
4276 vos_close(pVosContext );
4277
Jeff Johnson295189b2012-06-20 16:38:30 -07004278err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004279 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004280
4281err_wdclose:
4282 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4283 vos_watchdog_close(pVosContext);
4284
Jeff Johnson295189b2012-06-20 16:38:30 -07004285err_wiphy_reg:
4286 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004287
4288err_config:
4289 kfree(pHddCtx->cfg_ini);
4290 pHddCtx->cfg_ini= NULL;
4291
4292err_free_hdd_context:
4293 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004294 wiphy_free(wiphy) ;
4295 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004296 VOS_BUG(1);
4297
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08004298 if (hdd_is_ssr_required())
4299 {
4300 /* WDI timeout had happened during load, so SSR is needed here */
4301 subsystem_restart("wcnss");
4302 msleep(5000);
4303 }
4304 hdd_set_ssr_required (VOS_FALSE);
4305
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004306 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004307
4308success:
4309 EXIT();
4310 return 0;
4311}
4312
4313/**---------------------------------------------------------------------------
4314
Jeff Johnson32d95a32012-09-10 13:15:23 -07004315 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07004316
Jeff Johnson32d95a32012-09-10 13:15:23 -07004317 This is the driver entry point - called in different timeline depending
4318 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07004319
4320 \param - None
4321
4322 \return - 0 for success, non zero for failure
4323
4324 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07004325static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004326{
4327 VOS_STATUS status;
4328 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004329 struct device *dev = NULL;
4330 int ret_status = 0;
4331
4332 ENTER();
4333
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004334#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004335 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07004336#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004337
4338 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
4339 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
4340
4341 //Power Up Libra WLAN card first if not already powered up
4342 status = vos_chipPowerUp(NULL,NULL,NULL);
4343 if (!VOS_IS_STATUS_SUCCESS(status))
4344 {
4345 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
4346 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004347 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004348 }
4349
Jeff Johnson295189b2012-06-20 16:38:30 -07004350#ifdef ANI_BUS_TYPE_PCI
4351
4352 dev = wcnss_wlan_get_device();
4353
4354#endif // ANI_BUS_TYPE_PCI
4355
4356#ifdef ANI_BUS_TYPE_PLATFORM
4357 dev = wcnss_wlan_get_device();
4358#endif // ANI_BUS_TYPE_PLATFORM
4359
4360
4361 do {
4362 if (NULL == dev) {
4363 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
4364 ret_status = -1;
4365 break;
4366 }
4367
4368#ifdef MEMORY_DEBUG
4369 vos_mem_init();
4370#endif
4371
4372#ifdef TIMER_MANAGER
4373 vos_timer_manager_init();
4374#endif
4375
4376 /* Preopen VOSS so that it is ready to start at least SAL */
4377 status = vos_preOpen(&pVosContext);
4378
4379 if (!VOS_IS_STATUS_SUCCESS(status))
4380 {
4381 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
4382 ret_status = -1;
4383 break;
4384 }
4385
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004386#ifndef MODULE
4387 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
4388 */
4389 hdd_set_conparam((v_UINT_t)con_mode);
4390#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004391
4392 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004393 if (hdd_wlan_startup(dev))
4394 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004395 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004396 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004397 vos_preClose( &pVosContext );
4398 ret_status = -1;
4399 break;
4400 }
4401
4402 /* Cancel the vote for XO Core ON
4403 * This is done here for safety purposes in case we re-initialize without turning
4404 * it OFF in any error scenario.
4405 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004406 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07004407 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004408 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07004409 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4410 {
4411 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
4412 " Power consumed will be high\n");
4413 }
4414 } while (0);
4415
4416 if (0 != ret_status)
4417 {
4418 //Assert Deep sleep signal now to put Libra HW in lowest power state
4419 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4420 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
4421
4422 //Vote off any PMIC voltage supplies
4423 vos_chipPowerDown(NULL, NULL, NULL);
4424#ifdef TIMER_MANAGER
4425 vos_timer_exit();
4426#endif
4427#ifdef MEMORY_DEBUG
4428 vos_mem_exit();
4429#endif
4430
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004431#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004432 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004433#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004434 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
4435 }
4436 else
4437 {
4438 //Send WLAN UP indication to Nlink Service
4439 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
4440
4441 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
4442
4443 }
4444
4445 EXIT();
4446
4447 return ret_status;
4448}
4449
Jeff Johnson32d95a32012-09-10 13:15:23 -07004450/**---------------------------------------------------------------------------
4451
4452 \brief hdd_module_init() - Init Function
4453
4454 This is the driver entry point (invoked when module is loaded using insmod)
4455
4456 \param - None
4457
4458 \return - 0 for success, non zero for failure
4459
4460 --------------------------------------------------------------------------*/
4461#ifdef MODULE
4462static int __init hdd_module_init ( void)
4463{
4464 return hdd_driver_init();
4465}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004466#else /* #ifdef MODULE */
4467static int __init hdd_module_init ( void)
4468{
4469 /* Driver initialization is delayed to fwpath_changed_handler */
4470 return 0;
4471}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004472#endif /* #ifdef MODULE */
4473
Jeff Johnson295189b2012-06-20 16:38:30 -07004474
4475/**---------------------------------------------------------------------------
4476
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004477 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07004478
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004479 This is the driver exit point (invoked when module is unloaded using rmmod
4480 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07004481
4482 \param - None
4483
4484 \return - None
4485
4486 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004487static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004488{
4489 hdd_context_t *pHddCtx = NULL;
4490 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004491
4492 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
4493
4494 //Get the global vos context
4495 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4496
4497 if(!pVosContext)
4498 {
4499 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
4500 goto done;
4501 }
4502
4503 //Get the HDD context.
4504 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
4505
4506 if(!pHddCtx)
4507 {
4508 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
4509 }
4510 else
4511 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004512 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07004513 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07004514 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
4515 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07004516 }
4517
4518 pHddCtx->isLoadUnloadInProgress = TRUE;
4519 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4520
4521 //Do all the cleanup before deregistering the driver
4522 hdd_wlan_exit(pHddCtx);
4523 }
4524
Jeff Johnson295189b2012-06-20 16:38:30 -07004525 vos_preClose( &pVosContext );
4526
4527#ifdef TIMER_MANAGER
4528 vos_timer_exit();
4529#endif
4530#ifdef MEMORY_DEBUG
4531 vos_mem_exit();
4532#endif
4533
4534done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004535#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004536 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004537#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004538 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
4539}
4540
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004541/**---------------------------------------------------------------------------
4542
4543 \brief hdd_module_exit() - Exit function
4544
4545 This is the driver exit point (invoked when module is unloaded using rmmod)
4546
4547 \param - None
4548
4549 \return - None
4550
4551 --------------------------------------------------------------------------*/
4552static void __exit hdd_module_exit(void)
4553{
4554 hdd_driver_exit();
4555}
4556
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004557#ifdef MODULE
4558static int fwpath_changed_handler(const char *kmessage,
4559 struct kernel_param *kp)
4560{
4561 /* nothing to do when driver is DLKM */
4562 return 0;
4563}
4564
4565static int con_mode_handler(const char *kmessage,
4566 struct kernel_param *kp)
4567{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07004568 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004569}
4570#else /* #ifdef MODULE */
4571/**---------------------------------------------------------------------------
4572
4573 \brief fwpath_changed_handler() - Handler Function
4574
4575 This is the driver entry point
4576 - delayed driver initialization when driver is statically linked
4577 - invoked when module parameter fwpath is modified from userpspace to signal
4578 initializing the WLAN driver
4579
4580 \return - 0 for success, non zero for failure
4581
4582 --------------------------------------------------------------------------*/
4583static int fwpath_changed_handler(const char *kmessage,
4584 struct kernel_param *kp)
4585{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004586 int ret_status;
4587
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004588 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004589 ret_status = hdd_driver_init();
4590 wlan_hdd_inited = ret_status ? 0 : 1;
4591 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004592 }
4593
4594 hdd_driver_exit();
4595
4596 msleep(200);
4597
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004598 ret_status = hdd_driver_init();
4599 wlan_hdd_inited = ret_status ? 0 : 1;
4600 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004601}
4602
Jeff Johnson295189b2012-06-20 16:38:30 -07004603/**---------------------------------------------------------------------------
4604
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004605 \brief con_mode_handler() -
4606
4607 Handler function for module param con_mode when it is changed by userspace
4608 Dynamically linked - do nothing
4609 Statically linked - exit and init driver, as in rmmod and insmod
4610
4611 \param -
4612
4613 \return -
4614
4615 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004616static int con_mode_handler(const char *kmessage,
4617 struct kernel_param *kp)
4618{
4619 int ret = param_set_int(kmessage, kp);
4620
4621 if (ret)
4622 return ret;
4623
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004624 return fwpath_changed_handler(kmessage, kp);
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004625}
4626#endif /* #ifdef MODULE */
4627
4628/**---------------------------------------------------------------------------
4629
Jeff Johnson295189b2012-06-20 16:38:30 -07004630 \brief hdd_get_conparam() -
4631
4632 This is the driver exit point (invoked when module is unloaded using rmmod)
4633
4634 \param - None
4635
4636 \return - tVOS_CON_MODE
4637
4638 --------------------------------------------------------------------------*/
4639tVOS_CON_MODE hdd_get_conparam ( void )
4640{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004641#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07004642 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004643#else
4644 return (tVOS_CON_MODE)curr_con_mode;
4645#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004646}
4647void hdd_set_conparam ( v_UINT_t newParam )
4648{
4649 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004650#ifndef MODULE
4651 curr_con_mode = con_mode;
4652#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004653}
4654/**---------------------------------------------------------------------------
4655
4656 \brief hdd_softap_sta_deauth() - function
4657
4658 This to take counter measure to handle deauth req from HDD
4659
4660 \param - pAdapter - Pointer to the HDD
4661
4662 \param - enable - boolean value
4663
4664 \return - None
4665
4666 --------------------------------------------------------------------------*/
4667
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004668VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07004669{
Jeff Johnson295189b2012-06-20 16:38:30 -07004670 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004671 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07004672
4673 ENTER();
4674
4675 hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4676
4677 //Ignore request to deauth bcmc station
4678 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004679 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004680
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004681 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07004682
4683 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004684 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004685}
4686
4687/**---------------------------------------------------------------------------
4688
4689 \brief hdd_softap_sta_disassoc() - function
4690
4691 This to take counter measure to handle deauth req from HDD
4692
4693 \param - pAdapter - Pointer to the HDD
4694
4695 \param - enable - boolean value
4696
4697 \return - None
4698
4699 --------------------------------------------------------------------------*/
4700
4701void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
4702{
4703 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4704
4705 ENTER();
4706
4707 hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4708
4709 //Ignore request to disassoc bcmc station
4710 if( pDestMacAddress[0] & 0x1 )
4711 return;
4712
4713 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
4714}
4715
4716void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
4717{
4718 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4719
4720 ENTER();
4721
4722 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4723
4724 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
4725}
4726
Jeff Johnson295189b2012-06-20 16:38:30 -07004727/**---------------------------------------------------------------------------
4728 *
4729 * \brief hdd_get__concurrency_mode() -
4730 *
4731 *
4732 * \param - None
4733 *
4734 * \return - CONCURRENCY MODE
4735 *
4736 * --------------------------------------------------------------------------*/
4737tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
4738{
4739 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
4740 hdd_context_t *pHddCtx;
4741
4742 if (NULL != pVosContext)
4743 {
4744 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
4745 if (NULL != pHddCtx)
4746 {
4747 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
4748 }
4749 }
4750
4751 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004752 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004753 return VOS_STA;
4754}
4755
4756/* Decide whether to allow/not the apps power collapse.
4757 * Allow apps power collapse if we are in connected state.
4758 * if not, allow only if we are in IMPS */
4759v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
4760{
4761 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08004762 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07004763 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4764 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4765 hdd_adapter_t *pAdapter = NULL;
4766 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08004767 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004768
Jeff Johnson295189b2012-06-20 16:38:30 -07004769 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4770 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004771
Yathish9f22e662012-12-10 14:21:35 -08004772 concurrent_state = hdd_get_concurrency_mode();
4773
4774#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4775 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
4776 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
4777 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
4778 return TRUE;
4779#endif
4780
Jeff Johnson295189b2012-06-20 16:38:30 -07004781 /*loop through all adapters. TBD fix for Concurrency */
4782 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4783 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4784 {
4785 pAdapter = pAdapterNode->pAdapter;
4786 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4787 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4788 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08004789 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07004790 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08004791 && pmcState != STOPPED && pmcState != STANDBY)) ||
4792 (eANI_BOOLEAN_TRUE == scanRspPending))
Jeff Johnson295189b2012-06-20 16:38:30 -07004793 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08004794 hddLog( LOGE, "%s: do not allow APPS power collapse-"
4795 "pmcState = %d scanRspPending = %d",
4796 __func__, pmcState, scanRspPending );
Jeff Johnson295189b2012-06-20 16:38:30 -07004797 return FALSE;
4798 }
4799 }
4800 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4801 pAdapterNode = pNext;
4802 }
4803 return TRUE;
4804}
4805
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08004806/* Decides whether to send suspend notification to Riva
4807 * if any adapter is in BMPS; then it is required */
4808v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
4809{
4810 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
4811 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4812
4813 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
4814 {
4815 return TRUE;
4816 }
4817 return FALSE;
4818}
4819
Jeff Johnson295189b2012-06-20 16:38:30 -07004820void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
4821{
4822 switch(mode)
4823 {
4824 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07004825 case WLAN_HDD_P2P_CLIENT:
4826 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004827 case WLAN_HDD_SOFTAP:
Jeff Johnsone7245742012-09-05 17:12:55 -07004828 pHddCtx->concurrency_mode |= (1 << mode);
4829 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07004830 break;
4831 default:
4832 break;
4833
4834 }
4835 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
4836 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
4837}
4838
4839
4840void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
4841{
4842 switch(mode)
4843 {
4844 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07004845 case WLAN_HDD_P2P_CLIENT:
4846 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004847 case WLAN_HDD_SOFTAP:
4848 pHddCtx->no_of_sessions[mode]--;
4849 if (!(pHddCtx->no_of_sessions[mode]))
4850 pHddCtx->concurrency_mode &= (~(1 << mode));
4851 break;
4852 default:
4853 break;
4854 }
4855 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
4856 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
4857}
4858
Jeff Johnsone7245742012-09-05 17:12:55 -07004859/**---------------------------------------------------------------------------
4860 *
4861 * \brief wlan_hdd_restart_init
4862 *
4863 * This function initalizes restart timer/flag. An internal function.
4864 *
4865 * \param - pHddCtx
4866 *
4867 * \return - None
4868 *
4869 * --------------------------------------------------------------------------*/
4870
4871static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
4872{
4873 /* Initialize */
4874 pHddCtx->hdd_restart_retries = 0;
4875 atomic_set(&pHddCtx->isRestartInProgress, 0);
4876 vos_timer_init(&pHddCtx->hdd_restart_timer,
4877 VOS_TIMER_TYPE_SW,
4878 wlan_hdd_restart_timer_cb,
4879 pHddCtx);
4880}
4881/**---------------------------------------------------------------------------
4882 *
4883 * \brief wlan_hdd_restart_deinit
4884 *
4885 * This function cleans up the resources used. An internal function.
4886 *
4887 * \param - pHddCtx
4888 *
4889 * \return - None
4890 *
4891 * --------------------------------------------------------------------------*/
4892
4893static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
4894{
4895
4896 VOS_STATUS vos_status;
4897 /* Block any further calls */
4898 atomic_set(&pHddCtx->isRestartInProgress, 1);
4899 /* Cleanup */
4900 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
4901 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004902 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07004903 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
4904 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004905 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07004906
4907}
4908
4909/**---------------------------------------------------------------------------
4910 *
4911 * \brief wlan_hdd_framework_restart
4912 *
4913 * This function uses a cfg80211 API to start a framework initiated WLAN
4914 * driver module unload/load.
4915 *
4916 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
4917 *
4918 *
4919 * \param - pHddCtx
4920 *
4921 * \return - VOS_STATUS_SUCCESS: Success
4922 * VOS_STATUS_E_EMPTY: Adapter is Empty
4923 * VOS_STATUS_E_NOMEM: No memory
4924
4925 * --------------------------------------------------------------------------*/
4926
4927static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
4928{
4929 VOS_STATUS status = VOS_STATUS_SUCCESS;
4930 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4931 int len = (sizeof (struct ieee80211_mgmt));
4932 struct ieee80211_mgmt *mgmt = NULL;
4933
4934 /* Prepare the DEAUTH managment frame with reason code */
4935 mgmt = kzalloc(len, GFP_KERNEL);
4936 if(mgmt == NULL)
4937 {
4938 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1250df42012-12-10 14:31:52 -08004939 "%s: memory allocation failed (%d bytes)", __func__, len);
Jeff Johnsone7245742012-09-05 17:12:55 -07004940 return VOS_STATUS_E_NOMEM;
4941 }
4942 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
4943
4944 /* Iterate over all adapters/devices */
4945 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4946 do
4947 {
4948 if( (status == VOS_STATUS_SUCCESS) &&
4949 pAdapterNode &&
4950 pAdapterNode->pAdapter)
4951 {
4952 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4953 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
4954 pAdapterNode->pAdapter->dev->name,
4955 pAdapterNode->pAdapter->device_mode,
4956 pHddCtx->hdd_restart_retries + 1);
4957 /*
4958 * CFG80211 event to restart the driver
4959 *
4960 * 'cfg80211_send_unprot_deauth' sends a
4961 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
4962 * of SME(Linux Kernel) state machine.
4963 *
4964 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
4965 * the driver.
4966 *
4967 */
4968
4969 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
4970 }
4971 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4972 pAdapterNode = pNext;
4973 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
4974
4975
4976 /* Free the allocated management frame */
4977 kfree(mgmt);
4978
4979 /* Retry until we unload or reach max count */
4980 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
4981 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
4982
4983 return status;
4984
4985}
4986/**---------------------------------------------------------------------------
4987 *
4988 * \brief wlan_hdd_restart_timer_cb
4989 *
4990 * Restart timer callback. An internal function.
4991 *
4992 * \param - User data:
4993 *
4994 * \return - None
4995 *
4996 * --------------------------------------------------------------------------*/
4997
4998void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
4999{
5000 hdd_context_t *pHddCtx = usrDataForCallback;
5001 wlan_hdd_framework_restart(pHddCtx);
5002 return;
5003
5004}
5005
5006
5007/**---------------------------------------------------------------------------
5008 *
5009 * \brief wlan_hdd_restart_driver
5010 *
5011 * This function sends an event to supplicant to restart the WLAN driver.
5012 *
5013 * This function is called from vos_wlanRestart.
5014 *
5015 * \param - pHddCtx
5016 *
5017 * \return - VOS_STATUS_SUCCESS: Success
5018 * VOS_STATUS_E_EMPTY: Adapter is Empty
5019 * VOS_STATUS_E_ALREADY: Request already in progress
5020
5021 * --------------------------------------------------------------------------*/
5022VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
5023{
5024 VOS_STATUS status = VOS_STATUS_SUCCESS;
5025
5026 /* A tight check to make sure reentrancy */
5027 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
5028 {
5029 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
5030 "%s: WLAN restart is already in progress", __func__);
5031
5032 return VOS_STATUS_E_ALREADY;
5033 }
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005034 /* when WLAN driver is statically linked, then invoke SSR by sending
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005035 * the reset interrupt. If it is DLKM, then use restart API
5036 */
5037#ifdef MODULE
Jeff Johnsone7245742012-09-05 17:12:55 -07005038 status = wlan_hdd_framework_restart(pHddCtx);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005039#else
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005040#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005041 wcnss_reset_intr();
5042#endif
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005043#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005044
Jeff Johnsone7245742012-09-05 17:12:55 -07005045 return status;
5046}
5047
5048
Jeff Johnson295189b2012-06-20 16:38:30 -07005049//Register the module init/exit functions
5050module_init(hdd_module_init);
5051module_exit(hdd_module_exit);
5052
5053MODULE_LICENSE("Dual BSD/GPL");
5054MODULE_AUTHOR("Qualcomm Atheros, Inc.");
5055MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
5056
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005057module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
5058 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07005059
5060module_param_call(fwpath, fwpath_changed_handler, param_get_string, fwpath,
5061 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);