blob: 463e8e709399fbaa459704b18bc84a66ce1f4104 [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;
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700622 tANI_U16 emptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800623 /* 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 */
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700627 ret = kstrtou16(value, 10, &emptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800628 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__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700636 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
637 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800638 ret = -EINVAL;
639 goto exit;
640 }
641
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700642 emptyScanRefreshPeriod = emptyScanRefreshPeriod * 1000;
643 if ((emptyScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
644 (emptyScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800645 {
646 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700647 "Empty scan refresh period value %d is out of range"
648 " (Min: %d Max: %d)", emptyScanRefreshPeriod/1000,
649 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
650 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800651 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"
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700657 " (Empty Scan refresh period) = %d", __func__, emptyScanRefreshPeriod/1000);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800658
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700659 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = emptyScanRefreshPeriod;
660 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), emptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800661 }
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);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07001697 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07001698
Jeff Johnson295189b2012-06-20 16:38:30 -07001699 pAdapter->isLinkUpSvcNeeded = FALSE;
1700 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
1701 //Init the net_device structure
1702 strlcpy(pWlanDev->name, name, IFNAMSIZ);
1703
1704 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
1705 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
1706 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
1707 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
1708
1709 hdd_set_station_ops( pAdapter->dev );
1710
1711 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07001712 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
1713 pAdapter->wdev.wiphy = pHddCtx->wiphy;
1714 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07001715 /* set pWlanDev's parent to underlying device */
1716 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
1717 }
1718
1719 return pAdapter;
1720}
1721
1722VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
1723{
1724 struct net_device *pWlanDev = pAdapter->dev;
1725 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1726 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1727 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1728
1729 if( rtnl_lock_held )
1730 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001731 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07001732 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
1733 {
1734 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
1735 return VOS_STATUS_E_FAILURE;
1736 }
1737 }
1738 if (register_netdevice(pWlanDev))
1739 {
1740 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
1741 return VOS_STATUS_E_FAILURE;
1742 }
1743 }
1744 else
1745 {
1746 if(register_netdev(pWlanDev))
1747 {
1748 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
1749 return VOS_STATUS_E_FAILURE;
1750 }
1751 }
1752 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
1753
1754 return VOS_STATUS_SUCCESS;
1755}
1756
1757eHalStatus hdd_smeCloseSessionCallback(void *pContext)
1758{
1759 if(pContext != NULL)
1760 {
1761 clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags);
1762
1763 /* need to make sure all of our scheduled work has completed.
1764 * This callback is called from MC thread context, so it is safe to
1765 * to call below flush workqueue API from here.
1766 */
1767 flush_scheduled_work();
1768 complete(&((hdd_adapter_t*)pContext)->session_close_comp_var);
1769 }
1770 return eHAL_STATUS_SUCCESS;
1771}
1772
1773VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
1774{
1775 struct net_device *pWlanDev = pAdapter->dev;
1776 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1777 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1778 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1779 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1780 int rc = 0;
1781
1782 INIT_COMPLETION(pAdapter->session_open_comp_var);
1783 //Open a SME session for future operation
1784 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
1785 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
1786 if ( !HAL_STATUS_SUCCESS( halStatus ) )
1787 {
1788 hddLog(VOS_TRACE_LEVEL_FATAL,
1789 "sme_OpenSession() failed with status code %08d [x%08lx]",
1790 halStatus, halStatus );
1791 status = VOS_STATUS_E_FAILURE;
1792 goto error_sme_open;
1793 }
1794
1795 //Block on a completion variable. Can't wait forever though.
1796 rc = wait_for_completion_interruptible_timeout(
1797 &pAdapter->session_open_comp_var,
1798 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1799 if (!rc)
1800 {
1801 hddLog(VOS_TRACE_LEVEL_FATAL,
1802 "Session is not opened within timeout period code %08d", rc );
1803 status = VOS_STATUS_E_FAILURE;
1804 goto error_sme_open;
1805 }
1806
1807 // Register wireless extensions
1808 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
1809 {
1810 hddLog(VOS_TRACE_LEVEL_FATAL,
1811 "hdd_register_wext() failed with status code %08d [x%08lx]",
1812 halStatus, halStatus );
1813 status = VOS_STATUS_E_FAILURE;
1814 goto error_register_wext;
1815 }
1816 //Safe to register the hard_start_xmit function again
1817#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1818 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
1819#else
1820 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
1821#endif
1822
1823 //Set the Connection State to Not Connected
1824 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
1825
1826 //Set the default operation channel
1827 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
1828
1829 /* Make the default Auth Type as OPEN*/
1830 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
1831
1832 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
1833 {
1834 hddLog(VOS_TRACE_LEVEL_FATAL,
1835 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
1836 status, status );
1837 goto error_init_txrx;
1838 }
1839
1840 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1841
1842 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
1843 {
1844 hddLog(VOS_TRACE_LEVEL_FATAL,
1845 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
1846 status, status );
1847 goto error_wmm_init;
1848 }
1849
1850 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1851
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001852#ifdef FEATURE_WLAN_TDLS
1853 if(0 != wlan_hdd_tdls_init(pAdapter))
1854 {
1855 status = VOS_STATUS_E_FAILURE;
1856 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
1857 goto error_tdls_init;
1858 }
1859 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
1860#endif
1861
Jeff Johnson295189b2012-06-20 16:38:30 -07001862 return VOS_STATUS_SUCCESS;
1863
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001864#ifdef FEATURE_WLAN_TDLS
1865error_tdls_init:
1866 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1867 hdd_wmm_adapter_close(pAdapter);
1868#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001869error_wmm_init:
1870 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1871 hdd_deinit_tx_rx(pAdapter);
1872error_init_txrx:
1873 hdd_UnregisterWext(pWlanDev);
1874error_register_wext:
1875 if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
1876 {
1877 INIT_COMPLETION(pAdapter->session_close_comp_var);
1878 if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
1879 pAdapter->sessionId,
1880 hdd_smeCloseSessionCallback, pAdapter ) )
1881 {
1882 //Block on a completion variable. Can't wait forever though.
1883 wait_for_completion_interruptible_timeout(
1884 &pAdapter->session_close_comp_var,
1885 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1886 }
1887}
1888error_sme_open:
1889 return status;
1890}
1891
Jeff Johnson295189b2012-06-20 16:38:30 -07001892void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1893{
1894 hdd_cfg80211_state_t *cfgState;
1895
1896 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1897
1898 if( NULL != cfgState->buf )
1899 {
1900 int rc;
1901 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
1902 rc = wait_for_completion_interruptible_timeout(
1903 &pAdapter->tx_action_cnf_event,
1904 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
1905 if(!rc)
1906 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08001907 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001908 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
1909 }
1910 }
1911 return;
1912}
Jeff Johnson295189b2012-06-20 16:38:30 -07001913
1914void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1915{
1916 ENTER();
1917 switch ( pAdapter->device_mode )
1918 {
1919 case WLAN_HDD_INFRA_STATION:
1920 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07001921 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07001922 {
1923 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1924 {
1925 hdd_deinit_tx_rx( pAdapter );
1926 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1927 }
1928
1929 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
1930 {
1931 hdd_wmm_adapter_close( pAdapter );
1932 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1933 }
1934
Jeff Johnson295189b2012-06-20 16:38:30 -07001935 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001936#ifdef FEATURE_WLAN_TDLS
1937 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
1938 {
1939 wlan_hdd_tdls_exit(pAdapter);
1940 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
1941 }
1942#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001943
1944 break;
1945 }
1946
1947 case WLAN_HDD_SOFTAP:
1948 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07001949 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001950 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001951
1952 hdd_unregister_hostapd(pAdapter);
1953 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07001954 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07001955 break;
1956 }
1957
1958 case WLAN_HDD_MONITOR:
1959 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001960 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07001961 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1962 {
1963 hdd_deinit_tx_rx( pAdapter );
1964 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1965 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001966 if(NULL != pAdapterforTx)
1967 {
1968 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
1969 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001970 break;
1971 }
1972
1973
1974 default:
1975 break;
1976 }
1977
1978 EXIT();
1979}
1980
1981void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
1982{
1983 struct net_device *pWlanDev = pAdapter->dev;
1984
1985 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
1986 if( rtnl_held )
1987 {
1988 unregister_netdevice(pWlanDev);
1989 }
1990 else
1991 {
1992 unregister_netdev(pWlanDev);
1993 }
1994 // note that the pAdapter is no longer valid at this point
1995 // since the memory has been reclaimed
1996 }
1997
1998}
1999
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08002000void hdd_set_pwrparams(hdd_context_t *pHddCtx)
2001{
2002 tSirSetPowerParamsReq powerRequest = { 0 };
2003
2004 powerRequest.uIgnoreDTIM = 1;
2005
2006 if (pHddCtx->cfg_ini->enableModulatedDTIM)
2007 {
2008 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
2009 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2010 }
2011 else
2012 {
2013 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
2014 }
2015
2016 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
2017 *specified during Enter/Exit BMPS when LCD off*/
2018 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2019 NULL, eANI_BOOLEAN_FALSE);
2020 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2021 NULL, eANI_BOOLEAN_FALSE);
2022
2023 /* switch to the DTIM specified in cfg.ini */
2024 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2025 "Switch to DTIM%d", powerRequest.uListenInterval);
2026 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2027
2028}
2029
2030void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
2031{
2032 /*Switch back to DTIM 1*/
2033 tSirSetPowerParamsReq powerRequest = { 0 };
2034
2035 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
2036 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2037
2038 /* Update ignoreDTIM and ListedInterval in CFG with default values */
2039 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2040 NULL, eANI_BOOLEAN_FALSE);
2041 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2042 NULL, eANI_BOOLEAN_FALSE);
2043
2044 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2045 "Switch to DTIM%d",powerRequest.uListenInterval);
2046 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2047
2048}
2049
Jeff Johnson295189b2012-06-20 16:38:30 -07002050VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
2051{
2052 VOS_STATUS status = VOS_STATUS_SUCCESS;
2053
2054 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2055 {
2056 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2057 }
2058
2059 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2060 {
2061 sme_StartAutoBmpsTimer(pHddCtx->hHal);
2062 }
2063
2064 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2065 {
2066 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2067 }
2068
2069 return status;
2070}
2071
2072VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
2073{
2074 hdd_adapter_t *pAdapter = NULL;
2075 eHalStatus halStatus;
2076 VOS_STATUS status = VOS_STATUS_E_INVAL;
2077 v_BOOL_t disableBmps = FALSE;
2078 v_BOOL_t disableImps = FALSE;
2079
2080 switch(session_type)
2081 {
2082 case WLAN_HDD_INFRA_STATION:
2083 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002084 case WLAN_HDD_P2P_CLIENT:
2085 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002086 //Exit BMPS -> Is Sta/P2P Client is already connected
2087 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
2088 if((NULL != pAdapter)&&
2089 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2090 {
2091 disableBmps = TRUE;
2092 }
2093
2094 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
2095 if((NULL != pAdapter)&&
2096 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2097 {
2098 disableBmps = TRUE;
2099 }
2100
2101 //Exit both Bmps and Imps incase of Go/SAP Mode
2102 if((WLAN_HDD_SOFTAP == session_type) ||
2103 (WLAN_HDD_P2P_GO == session_type))
2104 {
2105 disableBmps = TRUE;
2106 disableImps = TRUE;
2107 }
2108
2109 if(TRUE == disableImps)
2110 {
2111 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2112 {
2113 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2114 }
2115 }
2116
2117 if(TRUE == disableBmps)
2118 {
2119 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2120 {
2121 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2122
2123 if(eHAL_STATUS_SUCCESS != halStatus)
2124 {
2125 status = VOS_STATUS_E_FAILURE;
2126 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
2127 VOS_ASSERT(0);
2128 return status;
2129 }
2130 }
2131
2132 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2133 {
2134 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
2135
2136 if(eHAL_STATUS_SUCCESS != halStatus)
2137 {
2138 status = VOS_STATUS_E_FAILURE;
2139 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
2140 VOS_ASSERT(0);
2141 return status;
2142 }
2143 }
2144 }
2145
2146 if((TRUE == disableBmps) ||
2147 (TRUE == disableImps))
2148 {
2149 /* Now, get the chip into Full Power now */
2150 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
2151 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
2152 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
2153
2154 if(halStatus != eHAL_STATUS_SUCCESS)
2155 {
2156 if(halStatus == eHAL_STATUS_PMC_PENDING)
2157 {
2158 //Block on a completion variable. Can't wait forever though
2159 wait_for_completion_interruptible_timeout(
2160 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
2161 }
2162 else
2163 {
2164 status = VOS_STATUS_E_FAILURE;
2165 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
2166 VOS_ASSERT(0);
2167 return status;
2168 }
2169 }
2170
2171 status = VOS_STATUS_SUCCESS;
2172 }
2173
2174 break;
2175 }
2176 return status;
2177}
2178
2179hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002180 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07002181 tANI_U8 rtnl_held )
2182{
2183 hdd_adapter_t *pAdapter = NULL;
2184 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
2185 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2186 VOS_STATUS exitbmpsStatus;
2187
2188 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
2189
2190 //Disable BMPS incase of Concurrency
2191 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
2192
2193 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
2194 {
2195 //Fail to Exit BMPS
2196 VOS_ASSERT(0);
2197 return NULL;
2198 }
2199
2200 switch(session_type)
2201 {
2202 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002203 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002204 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002205 {
2206 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2207
2208 if( NULL == pAdapter )
2209 return NULL;
2210
Jeff Johnsone7245742012-09-05 17:12:55 -07002211 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
2212 NL80211_IFTYPE_P2P_CLIENT:
2213 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07002214
Jeff Johnson295189b2012-06-20 16:38:30 -07002215 pAdapter->device_mode = session_type;
2216
2217 status = hdd_init_station_mode( pAdapter );
2218 if( VOS_STATUS_SUCCESS != status )
2219 goto err_free_netdev;
2220
2221 status = hdd_register_interface( pAdapter, rtnl_held );
2222 if( VOS_STATUS_SUCCESS != status )
2223 {
2224 hdd_deinit_adapter(pHddCtx, pAdapter);
2225 goto err_free_netdev;
2226 }
2227 //Stop the Interface TX queue.
2228 netif_tx_disable(pAdapter->dev);
2229 //netif_tx_disable(pWlanDev);
2230 netif_carrier_off(pAdapter->dev);
2231
2232 break;
2233 }
2234
Jeff Johnson295189b2012-06-20 16:38:30 -07002235 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002236 case WLAN_HDD_SOFTAP:
2237 {
2238 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
2239 if( NULL == pAdapter )
2240 return NULL;
2241
Jeff Johnson295189b2012-06-20 16:38:30 -07002242 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
2243 NL80211_IFTYPE_AP:
2244 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002245 pAdapter->device_mode = session_type;
2246
2247 status = hdd_init_ap_mode(pAdapter);
2248 if( VOS_STATUS_SUCCESS != status )
2249 goto err_free_netdev;
2250
2251 status = hdd_register_hostapd( pAdapter, rtnl_held );
2252 if( VOS_STATUS_SUCCESS != status )
2253 {
2254 hdd_deinit_adapter(pHddCtx, pAdapter);
2255 goto err_free_netdev;
2256 }
2257
2258 netif_tx_disable(pAdapter->dev);
2259 netif_carrier_off(pAdapter->dev);
2260
2261 hdd_set_conparam( 1 );
2262 break;
2263 }
2264 case WLAN_HDD_MONITOR:
2265 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002266 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2267 if( NULL == pAdapter )
2268 return NULL;
2269
2270 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
2271 pAdapter->device_mode = session_type;
2272 status = hdd_register_interface( pAdapter, rtnl_held );
2273#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
2274 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
2275#else
2276 pAdapter->dev->open = hdd_mon_open;
2277 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
2278#endif
2279 hdd_init_tx_rx( pAdapter );
2280 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2281 //Set adapter to be used for data tx. It will use either GO or softap.
2282 pAdapter->sessionCtx.monitor.pAdapterForTx =
2283 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07002284 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
2285 {
2286 pAdapter->sessionCtx.monitor.pAdapterForTx =
2287 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
2288 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002289 /* This workqueue will be used to transmit management packet over
2290 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07002291 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
2292 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
2293 return NULL;
2294 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07002295
Jeff Johnson295189b2012-06-20 16:38:30 -07002296 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
2297 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07002298 }
2299 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002300 case WLAN_HDD_FTM:
2301 {
2302 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2303
2304 if( NULL == pAdapter )
2305 return NULL;
2306 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
2307 * message while loading driver in FTM mode. */
2308 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
2309 pAdapter->device_mode = session_type;
2310 status = hdd_register_interface( pAdapter, rtnl_held );
2311 }
2312 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002313 default:
2314 {
2315 VOS_ASSERT(0);
2316 return NULL;
2317 }
2318 }
2319
2320
2321 if( VOS_STATUS_SUCCESS == status )
2322 {
2323 //Add it to the hdd's session list.
2324 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
2325 if( NULL == pHddAdapterNode )
2326 {
2327 status = VOS_STATUS_E_NOMEM;
2328 }
2329 else
2330 {
2331 pHddAdapterNode->pAdapter = pAdapter;
2332 status = hdd_add_adapter_back ( pHddCtx,
2333 pHddAdapterNode );
2334 }
2335 }
2336
2337 if( VOS_STATUS_SUCCESS != status )
2338 {
2339 if( NULL != pAdapter )
2340 {
2341 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
2342 pAdapter = NULL;
2343 }
2344 if( NULL != pHddAdapterNode )
2345 {
2346 vos_mem_free( pHddAdapterNode );
2347 }
2348
2349 goto resume_bmps;
2350 }
2351
2352 if(VOS_STATUS_SUCCESS == status)
2353 {
2354 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
2355
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07002356 //Initialize the WoWL service
2357 if(!hdd_init_wowl(pAdapter))
2358 {
2359 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
2360 goto err_free_netdev;
2361 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002362 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002363 return pAdapter;
2364
2365err_free_netdev:
2366 free_netdev(pAdapter->dev);
2367 wlan_hdd_release_intf_addr( pHddCtx,
2368 pAdapter->macAddressCurrent.bytes );
2369
2370resume_bmps:
2371 //If bmps disabled enable it
2372 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
2373 {
2374 hdd_enable_bmps_imps(pHddCtx);
2375 }
2376 return NULL;
2377}
2378
2379VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
2380 tANI_U8 rtnl_held )
2381{
2382 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
2383 VOS_STATUS status;
2384
2385 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
2386 if( VOS_STATUS_SUCCESS != status )
2387 return status;
2388
2389 while ( pCurrent->pAdapter != pAdapter )
2390 {
2391 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
2392 if( VOS_STATUS_SUCCESS != status )
2393 break;
2394
2395 pCurrent = pNext;
2396 }
2397 pAdapterNode = pCurrent;
2398 if( VOS_STATUS_SUCCESS == status )
2399 {
2400 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2401 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
2402 hdd_remove_adapter( pHddCtx, pAdapterNode );
2403 vos_mem_free( pAdapterNode );
2404
Jeff Johnson295189b2012-06-20 16:38:30 -07002405
2406 /* If there is a single session of STA/P2P client, re-enable BMPS */
2407 if ((!vos_concurrent_sessions_running()) &&
2408 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
2409 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
2410 {
2411 hdd_enable_bmps_imps(pHddCtx);
2412 }
2413
2414 return VOS_STATUS_SUCCESS;
2415 }
2416
2417 return VOS_STATUS_E_FAILURE;
2418}
2419
2420VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
2421{
2422 hdd_adapter_list_node_t *pHddAdapterNode;
2423 VOS_STATUS status;
2424
2425 ENTER();
2426
2427 do
2428 {
2429 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
2430 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
2431 {
2432 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
2433 vos_mem_free( pHddAdapterNode );
2434 }
2435 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
2436
2437 EXIT();
2438
2439 return VOS_STATUS_SUCCESS;
2440}
2441
2442void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
2443{
2444 v_U8_t addIE[1] = {0};
2445
2446 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2447 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
2448 eANI_BOOLEAN_FALSE) )
2449 {
2450 hddLog(LOGE,
2451 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
2452 }
2453
2454 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2455 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
2456 eANI_BOOLEAN_FALSE) )
2457 {
2458 hddLog(LOGE,
2459 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
2460 }
2461
2462 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2463 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
2464 eANI_BOOLEAN_FALSE) )
2465 {
2466 hddLog(LOGE,
2467 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
2468 }
2469}
2470
2471VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2472{
2473 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2474 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2475 union iwreq_data wrqu;
2476
2477 ENTER();
2478
2479 switch(pAdapter->device_mode)
2480 {
2481 case WLAN_HDD_INFRA_STATION:
2482 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002483 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002484 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
2485 {
2486 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
2487 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
2488 pAdapter->sessionId,
2489 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
2490 else
2491 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
2492 pAdapter->sessionId,
2493 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2494 //success implies disconnect command got queued up successfully
2495 if(halStatus == eHAL_STATUS_SUCCESS)
2496 {
2497 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
2498 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2499 }
2500 memset(&wrqu, '\0', sizeof(wrqu));
2501 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2502 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2503 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2504 }
2505 else
2506 {
2507 hdd_abort_mac_scan(pHddCtx);
2508 }
2509
2510 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
2511 {
2512 INIT_COMPLETION(pAdapter->session_close_comp_var);
2513 if (eHAL_STATUS_SUCCESS ==
2514 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
2515 hdd_smeCloseSessionCallback, pAdapter))
2516 {
2517 //Block on a completion variable. Can't wait forever though.
2518 wait_for_completion_interruptible_timeout(
2519 &pAdapter->session_close_comp_var,
2520 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2521 }
2522 }
2523
2524 break;
2525
2526 case WLAN_HDD_SOFTAP:
2527 case WLAN_HDD_P2P_GO:
2528 //Any softap specific cleanup here...
2529 mutex_lock(&pHddCtx->sap_lock);
2530 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2531 {
2532 VOS_STATUS status;
2533 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2534
2535 //Stop Bss.
2536 status = WLANSAP_StopBss(pHddCtx->pvosContext);
2537 if (VOS_IS_STATUS_SUCCESS(status))
2538 {
2539 hdd_hostapd_state_t *pHostapdState =
2540 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2541
2542 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2543
2544 if (!VOS_IS_STATUS_SUCCESS(status))
2545 {
2546 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002547 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002548 }
2549 }
2550 else
2551 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002552 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002553 }
2554 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2555
2556 if (eHAL_STATUS_FAILURE ==
2557 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
2558 0, NULL, eANI_BOOLEAN_FALSE))
2559 {
2560 hddLog(LOGE,
2561 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002562 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002563 }
2564
2565 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2566 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2567 eANI_BOOLEAN_FALSE) )
2568 {
2569 hddLog(LOGE,
2570 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
2571 }
2572
2573 // Reset WNI_CFG_PROBE_RSP Flags
2574 wlan_hdd_reset_prob_rspies(pAdapter);
2575 kfree(pAdapter->sessionCtx.ap.beacon);
2576 pAdapter->sessionCtx.ap.beacon = NULL;
2577 }
2578 mutex_unlock(&pHddCtx->sap_lock);
2579 break;
2580 case WLAN_HDD_MONITOR:
2581 break;
2582 default:
2583 break;
2584 }
2585
2586 EXIT();
2587 return VOS_STATUS_SUCCESS;
2588}
2589
2590VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
2591{
2592 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2593 VOS_STATUS status;
2594 hdd_adapter_t *pAdapter;
2595
2596 ENTER();
2597
2598 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2599
2600 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2601 {
2602 pAdapter = pAdapterNode->pAdapter;
2603 netif_tx_disable(pAdapter->dev);
2604 netif_carrier_off(pAdapter->dev);
2605
2606 hdd_stop_adapter( pHddCtx, pAdapter );
2607
2608 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2609 pAdapterNode = pNext;
2610 }
2611
2612 EXIT();
2613
2614 return VOS_STATUS_SUCCESS;
2615}
2616
2617VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
2618{
2619 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2620 VOS_STATUS status;
2621 hdd_adapter_t *pAdapter;
2622
2623 ENTER();
2624
2625 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2626
2627 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2628 {
2629 pAdapter = pAdapterNode->pAdapter;
2630 netif_tx_disable(pAdapter->dev);
2631 netif_carrier_off(pAdapter->dev);
2632
2633 //Record whether STA is associated
2634 pAdapter->sessionCtx.station.bSendDisconnect =
2635 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
2636 VOS_TRUE : VOS_FALSE;
2637
2638 hdd_deinit_tx_rx(pAdapter);
2639 hdd_wmm_adapter_close(pAdapter);
2640
2641 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2642 pAdapterNode = pNext;
2643 }
2644
2645 EXIT();
2646
2647 return VOS_STATUS_SUCCESS;
2648}
2649
2650VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
2651{
2652 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2653 VOS_STATUS status;
2654 hdd_adapter_t *pAdapter;
2655 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
2656
2657 ENTER();
2658
2659 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2660
2661 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2662 {
2663 pAdapter = pAdapterNode->pAdapter;
2664
2665 switch(pAdapter->device_mode)
2666 {
2667 case WLAN_HDD_INFRA_STATION:
2668 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002669 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002670 hdd_init_station_mode(pAdapter);
2671 /* Open the gates for HDD to receive Wext commands */
2672 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002673 pHddCtx->scan_info.mScanPending = FALSE;
2674 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002675
2676 //Trigger the initial scan
2677 hdd_wlan_initial_scan(pAdapter);
2678
2679 //Indicate disconnect event to supplicant if associated previously
2680 if(pAdapter->sessionCtx.station.bSendDisconnect)
2681 {
2682 union iwreq_data wrqu;
2683 memset(&wrqu, '\0', sizeof(wrqu));
2684 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2685 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2686 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2687 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
2688
Jeff Johnson295189b2012-06-20 16:38:30 -07002689 /* indicate disconnected event to nl80211 */
2690 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
2691 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002692 }
2693 break;
2694
2695 case WLAN_HDD_SOFTAP:
2696 /* softAP can handle SSR */
2697 break;
2698
2699 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002700 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
2701 __func__);
2702 /* event supplicant to restart */
2703 cfg80211_del_sta(pAdapter->dev,
2704 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002705 break;
2706
2707 case WLAN_HDD_MONITOR:
2708 /* monitor interface start */
2709 break;
2710 default:
2711 break;
2712 }
2713
2714 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2715 pAdapterNode = pNext;
2716 }
2717
2718 EXIT();
2719
2720 return VOS_STATUS_SUCCESS;
2721}
2722
2723VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
2724{
2725 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2726 hdd_adapter_t *pAdapter;
2727 VOS_STATUS status;
2728 v_U32_t roamId;
2729
2730 ENTER();
2731
2732 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2733
2734 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2735 {
2736 pAdapter = pAdapterNode->pAdapter;
2737
2738 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
2739 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
2740 {
2741 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2742 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2743
2744 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2745 init_completion(&pAdapter->disconnect_comp_var);
2746 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
2747 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2748
2749 wait_for_completion_interruptible_timeout(
2750 &pAdapter->disconnect_comp_var,
2751 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2752
2753 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
2754 pHddCtx->isAmpAllowed = VOS_FALSE;
2755 sme_RoamConnect(pHddCtx->hHal,
2756 pAdapter->sessionId, &(pWextState->roamProfile),
2757 &roamId);
2758 }
2759
2760 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2761 pAdapterNode = pNext;
2762 }
2763
2764 EXIT();
2765
2766 return VOS_STATUS_SUCCESS;
2767}
2768
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002769bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07002770{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002771 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07002772}
2773
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002774/* Once SSR is disabled then it cannot be set. */
2775void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07002776{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002777 if (HDD_SSR_DISABLED == isSsrRequired)
2778 return;
2779
Jeff Johnson295189b2012-06-20 16:38:30 -07002780 isSsrRequired = value;
2781}
2782
2783VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
2784 hdd_adapter_list_node_t** ppAdapterNode)
2785{
2786 VOS_STATUS status;
2787 spin_lock(&pHddCtx->hddAdapters.lock);
2788 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
2789 (hdd_list_node_t**) ppAdapterNode );
2790 spin_unlock(&pHddCtx->hddAdapters.lock);
2791 return status;
2792}
2793
2794VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
2795 hdd_adapter_list_node_t* pAdapterNode,
2796 hdd_adapter_list_node_t** pNextAdapterNode)
2797{
2798 VOS_STATUS status;
2799 spin_lock(&pHddCtx->hddAdapters.lock);
2800 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
2801 (hdd_list_node_t*) pAdapterNode,
2802 (hdd_list_node_t**)pNextAdapterNode );
2803
2804 spin_unlock(&pHddCtx->hddAdapters.lock);
2805 return status;
2806}
2807
2808VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
2809 hdd_adapter_list_node_t* pAdapterNode)
2810{
2811 VOS_STATUS status;
2812 spin_lock(&pHddCtx->hddAdapters.lock);
2813 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
2814 &pAdapterNode->node );
2815 spin_unlock(&pHddCtx->hddAdapters.lock);
2816 return status;
2817}
2818
2819VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
2820 hdd_adapter_list_node_t** ppAdapterNode)
2821{
2822 VOS_STATUS status;
2823 spin_lock(&pHddCtx->hddAdapters.lock);
2824 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
2825 (hdd_list_node_t**) ppAdapterNode );
2826 spin_unlock(&pHddCtx->hddAdapters.lock);
2827 return status;
2828}
2829
2830VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
2831 hdd_adapter_list_node_t* pAdapterNode)
2832{
2833 VOS_STATUS status;
2834 spin_lock(&pHddCtx->hddAdapters.lock);
2835 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
2836 (hdd_list_node_t*) pAdapterNode );
2837 spin_unlock(&pHddCtx->hddAdapters.lock);
2838 return status;
2839}
2840
2841VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
2842 hdd_adapter_list_node_t* pAdapterNode)
2843{
2844 VOS_STATUS status;
2845 spin_lock(&pHddCtx->hddAdapters.lock);
2846 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
2847 (hdd_list_node_t*) pAdapterNode );
2848 spin_unlock(&pHddCtx->hddAdapters.lock);
2849 return status;
2850}
2851
2852hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
2853 tSirMacAddr macAddr )
2854{
2855 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2856 hdd_adapter_t *pAdapter;
2857 VOS_STATUS status;
2858
2859 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2860
2861 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2862 {
2863 pAdapter = pAdapterNode->pAdapter;
2864
2865 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
2866 macAddr, sizeof(tSirMacAddr) ) )
2867 {
2868 return pAdapter;
2869 }
2870 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2871 pAdapterNode = pNext;
2872 }
2873
2874 return NULL;
2875
2876}
2877
2878hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
2879{
2880 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2881 hdd_adapter_t *pAdapter;
2882 VOS_STATUS status;
2883
2884 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2885
2886 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2887 {
2888 pAdapter = pAdapterNode->pAdapter;
2889
2890 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
2891 IFNAMSIZ ) )
2892 {
2893 return pAdapter;
2894 }
2895 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2896 pAdapterNode = pNext;
2897 }
2898
2899 return NULL;
2900
2901}
2902
2903hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
2904{
2905 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2906 hdd_adapter_t *pAdapter;
2907 VOS_STATUS status;
2908
2909 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2910
2911 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2912 {
2913 pAdapter = pAdapterNode->pAdapter;
2914
2915 if( pAdapter && (mode == pAdapter->device_mode) )
2916 {
2917 return pAdapter;
2918 }
2919 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2920 pAdapterNode = pNext;
2921 }
2922
2923 return NULL;
2924
2925}
2926
2927//Remove this function later
2928hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
2929{
2930 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2931 hdd_adapter_t *pAdapter;
2932 VOS_STATUS status;
2933
2934 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2935
2936 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2937 {
2938 pAdapter = pAdapterNode->pAdapter;
2939
2940 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
2941 {
2942 return pAdapter;
2943 }
2944
2945 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2946 pAdapterNode = pNext;
2947 }
2948
2949 return NULL;
2950
2951}
2952
Jeff Johnson295189b2012-06-20 16:38:30 -07002953/**---------------------------------------------------------------------------
2954
2955 \brief hdd_set_monitor_tx_adapter() -
2956
2957 This API initializes the adapter to be used while transmitting on monitor
2958 adapter.
2959
2960 \param - pHddCtx - Pointer to the HDD context.
2961 pAdapter - Adapter that will used for TX. This can be NULL.
2962 \return - None.
2963 --------------------------------------------------------------------------*/
2964void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2965{
2966 hdd_adapter_t *pMonAdapter;
2967
2968 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
2969
2970 if( NULL != pMonAdapter )
2971 {
2972 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
2973 }
2974}
Jeff Johnson295189b2012-06-20 16:38:30 -07002975/**---------------------------------------------------------------------------
2976
2977 \brief hdd_select_queue() -
2978
2979 This API returns the operating channel of the requested device mode
2980
2981 \param - pHddCtx - Pointer to the HDD context.
2982 - mode - Device mode for which operating channel is required
2983 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
2984 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
2985 \return - channel number. "0" id the requested device is not found OR it is not connected.
2986 --------------------------------------------------------------------------*/
2987v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
2988{
2989 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2990 VOS_STATUS status;
2991 hdd_adapter_t *pAdapter;
2992 v_U8_t operatingChannel = 0;
2993
2994 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2995
2996 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2997 {
2998 pAdapter = pAdapterNode->pAdapter;
2999
3000 if( mode == pAdapter->device_mode )
3001 {
3002 switch(pAdapter->device_mode)
3003 {
3004 case WLAN_HDD_INFRA_STATION:
3005 case WLAN_HDD_P2P_CLIENT:
3006 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3007 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
3008 break;
3009 case WLAN_HDD_SOFTAP:
3010 case WLAN_HDD_P2P_GO:
3011 /*softap connection info */
3012 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3013 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
3014 break;
3015 default:
3016 break;
3017 }
3018
3019 break; //Found the device of interest. break the loop
3020 }
3021
3022 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3023 pAdapterNode = pNext;
3024 }
3025 return operatingChannel;
3026}
3027
3028#ifdef WLAN_FEATURE_PACKET_FILTERING
3029/**---------------------------------------------------------------------------
3030
3031 \brief hdd_set_multicast_list() -
3032
3033 This used to set the multicast address list.
3034
3035 \param - dev - Pointer to the WLAN device.
3036 - skb - Pointer to OS packet (sk_buff).
3037 \return - success/fail
3038
3039 --------------------------------------------------------------------------*/
3040static void hdd_set_multicast_list(struct net_device *dev)
3041{
3042 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07003043 int mc_count;
3044 int i = 0;
3045 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303046
3047 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07003048 {
3049 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303050 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003051 return;
3052 }
3053
3054 if (dev->flags & IFF_ALLMULTI)
3055 {
3056 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003057 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303058 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003059 }
3060 else
3061 {
3062 mc_count = netdev_mc_count(dev);
3063 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003064 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07003065 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
3066 {
3067 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003068 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303069 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003070 return;
3071 }
3072
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303073 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07003074
3075 netdev_for_each_mc_addr(ha, dev) {
3076 if (i == mc_count)
3077 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303078 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
3079 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
3080 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003081 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303082 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07003083 i++;
3084 }
3085 }
3086 return;
3087}
3088#endif
3089
3090/**---------------------------------------------------------------------------
3091
3092 \brief hdd_select_queue() -
3093
3094 This function is registered with the Linux OS for network
3095 core to decide which queue to use first.
3096
3097 \param - dev - Pointer to the WLAN device.
3098 - skb - Pointer to OS packet (sk_buff).
3099 \return - ac, Queue Index/access category corresponding to UP in IP header
3100
3101 --------------------------------------------------------------------------*/
3102v_U16_t hdd_select_queue(struct net_device *dev,
3103 struct sk_buff *skb)
3104{
3105 return hdd_wmm_select_queue(dev, skb);
3106}
3107
3108
3109/**---------------------------------------------------------------------------
3110
3111 \brief hdd_wlan_initial_scan() -
3112
3113 This function triggers the initial scan
3114
3115 \param - pAdapter - Pointer to the HDD adapter.
3116
3117 --------------------------------------------------------------------------*/
3118void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
3119{
3120 tCsrScanRequest scanReq;
3121 tCsrChannelInfo channelInfo;
3122 eHalStatus halStatus;
3123 unsigned long scanId;
3124 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3125
3126 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
3127 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
3128 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
3129
3130 if(sme_Is11dSupported(pHddCtx->hHal))
3131 {
3132 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
3133 if ( HAL_STATUS_SUCCESS( halStatus ) )
3134 {
3135 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
3136 if( !scanReq.ChannelInfo.ChannelList )
3137 {
3138 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
3139 vos_mem_free(channelInfo.ChannelList);
3140 return;
3141 }
3142 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
3143 channelInfo.numOfChannels);
3144 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
3145 vos_mem_free(channelInfo.ChannelList);
3146 }
3147
3148 scanReq.scanType = eSIR_PASSIVE_SCAN;
3149 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
3150 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
3151 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
3152 }
3153 else
3154 {
3155 scanReq.scanType = eSIR_ACTIVE_SCAN;
3156 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
3157 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
3158 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
3159 }
3160
3161 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
3162 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3163 {
3164 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
3165 __func__, halStatus );
3166 }
3167
3168 if(sme_Is11dSupported(pHddCtx->hHal))
3169 vos_mem_free(scanReq.ChannelInfo.ChannelList);
3170}
3171
3172struct fullPowerContext
3173{
3174 struct completion completion;
3175 unsigned int magic;
3176};
3177#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
3178
3179/**---------------------------------------------------------------------------
3180
3181 \brief hdd_full_power_callback() - HDD full power callback function
3182
3183 This is the function invoked by SME to inform the result of a full power
3184 request issued by HDD
3185
3186 \param - callbackcontext - Pointer to cookie
3187 \param - status - result of request
3188
3189 \return - None
3190
3191 --------------------------------------------------------------------------*/
3192static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
3193{
3194 struct fullPowerContext *pContext = callbackContext;
3195
3196 hddLog(VOS_TRACE_LEVEL_INFO,
3197 "%s: context = %p, status = %d", pContext, status);
3198
3199 if (NULL == callbackContext)
3200 {
3201 hddLog(VOS_TRACE_LEVEL_ERROR,
3202 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003203 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07003204 return;
3205 }
3206
3207 /* there is a race condition that exists between this callback function
3208 and the caller since the caller could time out either before or
3209 while this code is executing. we'll assume the timeout hasn't
3210 occurred, but we'll verify that right before we save our work */
3211
3212 if (POWER_CONTEXT_MAGIC != pContext->magic)
3213 {
3214 /* the caller presumably timed out so there is nothing we can do */
3215 hddLog(VOS_TRACE_LEVEL_WARN,
3216 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003217 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07003218 return;
3219 }
3220
3221 /* the race is on. caller could have timed out immediately after
3222 we verified the magic, but if so, caller will wait a short time
3223 for us to notify the caller, so the context will stay valid */
3224 complete(&pContext->completion);
3225}
3226
3227/**---------------------------------------------------------------------------
3228
3229 \brief hdd_wlan_exit() - HDD WLAN exit function
3230
3231 This is the driver exit point (invoked during rmmod)
3232
3233 \param - pHddCtx - Pointer to the HDD Context
3234
3235 \return - None
3236
3237 --------------------------------------------------------------------------*/
3238void hdd_wlan_exit(hdd_context_t *pHddCtx)
3239{
3240 eHalStatus halStatus;
3241 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
3242 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05303243 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003244 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003245 struct fullPowerContext powerContext;
3246 long lrc;
3247
3248 ENTER();
3249
Jeff Johnson88ba7742013-02-27 14:36:02 -08003250 if (VOS_FTM_MODE != hdd_get_conparam())
3251 {
3252 // Unloading, restart logic is no more required.
3253 wlan_hdd_restart_deinit(pHddCtx);
3254 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003255
Jeff Johnson295189b2012-06-20 16:38:30 -07003256 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003257 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003258 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003259 {
3260 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
3261 WLAN_HDD_INFRA_STATION);
3262 if (pAdapter == NULL)
3263 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3264
3265 if (pAdapter != NULL)
3266 {
3267 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
3268 hdd_UnregisterWext(pAdapter->dev);
3269 }
3270 }
3271 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003272
Jeff Johnson295189b2012-06-20 16:38:30 -07003273 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08003274 {
3275 wlan_hdd_ftm_close(pHddCtx);
3276 goto free_hdd_ctx;
3277 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003278 //Stop the Interface TX queue.
3279 //netif_tx_disable(pWlanDev);
3280 //netif_carrier_off(pWlanDev);
3281
Jeff Johnson295189b2012-06-20 16:38:30 -07003282 if (VOS_STA_SAP_MODE == hdd_get_conparam())
3283 {
3284 pAdapter = hdd_get_adapter(pHddCtx,
3285 WLAN_HDD_SOFTAP);
3286 }
3287 else
3288 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003289 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003290 {
3291 pAdapter = hdd_get_adapter(pHddCtx,
3292 WLAN_HDD_INFRA_STATION);
3293 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003294 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003295 /* DeRegister with platform driver as client for Suspend/Resume */
3296 vosStatus = hddDeregisterPmOps(pHddCtx);
3297 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3298 {
3299 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
3300 VOS_ASSERT(0);
3301 }
3302
3303 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
3304 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3305 {
3306 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
3307 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003308
3309 // Cancel any outstanding scan requests. We are about to close all
3310 // of our adapters, but an adapter structure is what SME passes back
3311 // to our callback function. Hence if there are any outstanding scan
3312 // requests then there is a race condition between when the adapter
3313 // is closed and when the callback is invoked. We try to resolve that
3314 // race condition here by canceling any outstanding scans before we
3315 // close the adapters.
3316 // Note that the scans may be cancelled in an asynchronous manner, so
3317 // ideally there needs to be some kind of synchronization. Rather than
3318 // introduce a new synchronization here, we will utilize the fact that
3319 // we are about to Request Full Power, and since that is synchronized,
3320 // the expectation is that by the time Request Full Power has completed,
3321 // all scans will be cancelled.
3322 hdd_abort_mac_scan( pHddCtx );
3323
3324 //Disable IMPS/BMPS as we do not want the device to enter any power
3325 //save mode during shutdown
3326 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3327 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3328 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
3329
3330 //Ensure that device is in full power as we will touch H/W during vos_Stop
3331 init_completion(&powerContext.completion);
3332 powerContext.magic = POWER_CONTEXT_MAGIC;
3333
3334 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
3335 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
3336
3337 if (eHAL_STATUS_SUCCESS != halStatus)
3338 {
3339 if (eHAL_STATUS_PMC_PENDING == halStatus)
3340 {
3341 /* request was sent -- wait for the response */
3342 lrc = wait_for_completion_interruptible_timeout(
3343 &powerContext.completion,
3344 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
3345 /* either we have a response or we timed out
3346 either way, first invalidate our magic */
3347 powerContext.magic = 0;
3348 if (lrc <= 0)
3349 {
3350 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003351 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07003352 /* there is a race condition such that the callback
3353 function could be executing at the same time we are. of
3354 primary concern is if the callback function had already
3355 verified the "magic" but hasn't yet set the completion
3356 variable. Since the completion variable is on our
3357 stack, we'll delay just a bit to make sure the data is
3358 still valid if that is the case */
3359 msleep(50);
3360 }
3361 }
3362 else
3363 {
3364 hddLog(VOS_TRACE_LEVEL_ERROR,
3365 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003366 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07003367 VOS_ASSERT(0);
3368 /* continue -- need to clean up as much as possible */
3369 }
3370 }
3371
3372 // Unregister the Net Device Notifier
3373 unregister_netdevice_notifier(&hdd_netdev_notifier);
3374
Jeff Johnson295189b2012-06-20 16:38:30 -07003375 hdd_stop_all_adapters( pHddCtx );
3376
Jeff Johnson295189b2012-06-20 16:38:30 -07003377#ifdef WLAN_BTAMP_FEATURE
3378 vosStatus = WLANBAP_Stop(pVosContext);
3379 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3380 {
3381 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3382 "%s: Failed to stop BAP",__func__);
3383 }
3384#endif //WLAN_BTAMP_FEATURE
3385
3386 //Stop all the modules
3387 vosStatus = vos_stop( pVosContext );
3388 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3389 {
3390 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3391 "%s: Failed to stop VOSS",__func__);
3392 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3393 }
3394
Jeff Johnson295189b2012-06-20 16:38:30 -07003395 //Assert Deep sleep signal now to put Libra HW in lowest power state
3396 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
3397 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3398
3399 //Vote off any PMIC voltage supplies
3400 vos_chipPowerDown(NULL, NULL, NULL);
3401
3402 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
3403
3404 //Clean up HDD Nlink Service
3405 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
3406 nl_srv_exit();
3407
3408 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07003409 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003410
3411 //Close the scheduler before calling vos_close to make sure no thread is
3412 // scheduled after the each module close is called i.e after all the data
3413 // structures are freed.
3414 vosStatus = vos_sched_close( pVosContext );
3415 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
3416 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
3417 "%s: Failed to close VOSS Scheduler",__func__);
3418 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3419 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003420#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07003421#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3422 /* Destroy the wake lock */
3423 wake_lock_destroy(&pHddCtx->rx_wake_lock);
3424#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08003425 /* Destroy the wake lock */
3426 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003427#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003428
3429 //Close VOSS
3430 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
3431 vos_close(pVosContext);
3432
Jeff Johnson295189b2012-06-20 16:38:30 -07003433 //Close Watchdog
3434 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3435 vos_watchdog_close(pVosContext);
3436
3437 /* Cancel the vote for XO Core ON.
3438 * This is done here to ensure there is no race condition since MC, TX and WD threads have
3439 * exited at this point
3440 */
3441 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
3442 " when WLAN is turned OFF\n");
3443 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
3444 {
3445 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
3446 " Not returning failure."
3447 " Power consumed will be high\n");
3448 }
3449
3450 hdd_close_all_adapters( pHddCtx );
3451
3452
3453 //Free up dynamically allocated members inside HDD Adapter
3454 kfree(pHddCtx->cfg_ini);
3455 pHddCtx->cfg_ini= NULL;
3456
3457 /* free the power on lock from platform driver */
3458 if (free_riva_power_on_lock("wlan"))
3459 {
3460 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
3461 __func__);
3462 }
3463
Jeff Johnson88ba7742013-02-27 14:36:02 -08003464free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08003465 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07003466 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07003467 if (hdd_is_ssr_required())
3468 {
3469 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07003470 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07003471 msleep(5000);
3472 }
3473 hdd_set_ssr_required (VOS_FALSE);
3474}
3475
3476
3477/**---------------------------------------------------------------------------
3478
3479 \brief hdd_update_config_from_nv() - Function to update the contents of
3480 the running configuration with parameters taken from NV storage
3481
3482 \param - pHddCtx - Pointer to the HDD global context
3483
3484 \return - VOS_STATUS_SUCCESS if successful
3485
3486 --------------------------------------------------------------------------*/
3487static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
3488{
Jeff Johnson295189b2012-06-20 16:38:30 -07003489 v_BOOL_t itemIsValid = VOS_FALSE;
3490 VOS_STATUS status;
3491 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
3492 v_U8_t macLoop;
3493
3494 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
3495 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
3496 if(status != VOS_STATUS_SUCCESS)
3497 {
3498 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
3499 return VOS_STATUS_E_FAILURE;
3500 }
3501
3502 if (itemIsValid == VOS_TRUE)
3503 {
3504 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
3505 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
3506 VOS_MAX_CONCURRENCY_PERSONA);
3507 if(status != VOS_STATUS_SUCCESS)
3508 {
3509 /* Get MAC from NV fail, not update CFG info
3510 * INI MAC value will be used for MAC setting */
3511 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
3512 return VOS_STATUS_E_FAILURE;
3513 }
3514
3515 /* If first MAC is not valid, treat all others are not valid
3516 * Then all MACs will be got from ini file */
3517 if(vos_is_macaddr_zero(&macFromNV[0]))
3518 {
3519 /* MAC address in NV file is not configured yet */
3520 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
3521 return VOS_STATUS_E_INVAL;
3522 }
3523
3524 /* Get MAC address from NV, update CFG info */
3525 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
3526 {
3527 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
3528 {
3529 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
3530 /* This MAC is not valid, skip it
3531 * This MAC will be got from ini file */
3532 }
3533 else
3534 {
3535 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
3536 (v_U8_t *)&macFromNV[macLoop].bytes[0],
3537 VOS_MAC_ADDR_SIZE);
3538 }
3539 }
3540 }
3541 else
3542 {
3543 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
3544 return VOS_STATUS_E_FAILURE;
3545 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003546
Jeff Johnson295189b2012-06-20 16:38:30 -07003547
3548 return VOS_STATUS_SUCCESS;
3549}
3550
3551/**---------------------------------------------------------------------------
3552
3553 \brief hdd_post_voss_start_config() - HDD post voss start config helper
3554
3555 \param - pAdapter - Pointer to the HDD
3556
3557 \return - None
3558
3559 --------------------------------------------------------------------------*/
3560VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
3561{
3562 eHalStatus halStatus;
3563 v_U32_t listenInterval;
3564
Jeff Johnson295189b2012-06-20 16:38:30 -07003565
3566 // Send ready indication to the HDD. This will kick off the MAC
3567 // into a 'running' state and should kick off an initial scan.
3568 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
3569 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3570 {
3571 hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
3572 "code %08d [x%08x]",__func__, halStatus, halStatus );
3573 return VOS_STATUS_E_FAILURE;
3574 }
3575
3576 // Set default LI into HDD context,
3577 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
3578 // And RIVA will crash
3579 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
3580 pHddCtx->hdd_actual_LI_value = listenInterval;
3581
3582 return VOS_STATUS_SUCCESS;
3583}
3584
Jeff Johnson295189b2012-06-20 16:38:30 -07003585/* wake lock APIs for HDD */
3586void hdd_prevent_suspend(void)
3587{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003588#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003589 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003590#else
3591 wcnss_prevent_suspend();
3592#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003593}
3594
3595void hdd_allow_suspend(void)
3596{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003597#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003598 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003599#else
3600 wcnss_allow_suspend();
3601#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003602}
3603
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003604void hdd_allow_suspend_timeout(v_U32_t timeout)
3605{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003606#ifdef WLAN_OPEN_SOURCE
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003607 wake_lock_timeout(&wlan_wake_lock, timeout);
3608#else
3609 /* Do nothing as there is no API in wcnss for timeout*/
3610#endif
3611}
3612
Jeff Johnson295189b2012-06-20 16:38:30 -07003613/**---------------------------------------------------------------------------
3614
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003615 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
3616 information between Host and Riva
3617
3618 This function gets reported version of FW
3619 It also finds the version of Riva headers used to compile the host
3620 It compares the above two and prints a warning if they are different
3621 It gets the SW and HW version string
3622 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
3623 indicating the features they support through a bitmap
3624
3625 \param - pHddCtx - Pointer to HDD context
3626
3627 \return - void
3628
3629 --------------------------------------------------------------------------*/
3630
3631void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
3632{
3633
3634 tSirVersionType versionCompiled;
3635 tSirVersionType versionReported;
3636 tSirVersionString versionString;
3637 tANI_U8 fwFeatCapsMsgSupported = 0;
3638 VOS_STATUS vstatus;
3639
3640 /* retrieve and display WCNSS version information */
3641 do {
3642
3643 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
3644 &versionCompiled);
3645 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3646 {
3647 hddLog(VOS_TRACE_LEVEL_FATAL,
3648 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003649 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003650 break;
3651 }
3652
3653 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
3654 &versionReported);
3655 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3656 {
3657 hddLog(VOS_TRACE_LEVEL_FATAL,
3658 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003659 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003660 break;
3661 }
3662
3663 if ((versionCompiled.major != versionReported.major) ||
3664 (versionCompiled.minor != versionReported.minor) ||
3665 (versionCompiled.version != versionReported.version) ||
3666 (versionCompiled.revision != versionReported.revision))
3667 {
3668 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
3669 "Host expected %u.%u.%u.%u\n",
3670 WLAN_MODULE_NAME,
3671 (int)versionReported.major,
3672 (int)versionReported.minor,
3673 (int)versionReported.version,
3674 (int)versionReported.revision,
3675 (int)versionCompiled.major,
3676 (int)versionCompiled.minor,
3677 (int)versionCompiled.version,
3678 (int)versionCompiled.revision);
3679 }
3680 else
3681 {
3682 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
3683 WLAN_MODULE_NAME,
3684 (int)versionReported.major,
3685 (int)versionReported.minor,
3686 (int)versionReported.version,
3687 (int)versionReported.revision);
3688 }
3689
3690 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
3691 versionString,
3692 sizeof(versionString));
3693 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3694 {
3695 hddLog(VOS_TRACE_LEVEL_FATAL,
3696 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003697 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003698 break;
3699 }
3700
3701 pr_info("%s: WCNSS software version %s\n",
3702 WLAN_MODULE_NAME, versionString);
3703
3704 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
3705 versionString,
3706 sizeof(versionString));
3707 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3708 {
3709 hddLog(VOS_TRACE_LEVEL_FATAL,
3710 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003711 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003712 break;
3713 }
3714
3715 pr_info("%s: WCNSS hardware version %s\n",
3716 WLAN_MODULE_NAME, versionString);
3717
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003718 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
3719 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003720 send the message only if it the riva is 1.1
3721 minor numbers for different riva branches:
3722 0 -> (1.0)Mainline Build
3723 1 -> (1.1)Mainline Build
3724 2->(1.04) Stability Build
3725 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003726 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003727 ((versionReported.minor>=1) && (versionReported.version>=1)))
3728 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
3729 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003730
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003731 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08003732 {
3733#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
3734 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
3735 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
3736#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003737 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08003738 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003739
3740 } while (0);
3741
3742}
3743
3744/**---------------------------------------------------------------------------
3745
Jeff Johnson295189b2012-06-20 16:38:30 -07003746 \brief hdd_wlan_startup() - HDD init function
3747
3748 This is the driver startup code executed once a WLAN device has been detected
3749
3750 \param - dev - Pointer to the underlying device
3751
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003752 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07003753
3754 --------------------------------------------------------------------------*/
3755
3756int hdd_wlan_startup(struct device *dev )
3757{
3758 VOS_STATUS status;
3759 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003760 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003761 hdd_context_t *pHddCtx = NULL;
3762 v_CONTEXT_t pVosContext= NULL;
3763#ifdef WLAN_BTAMP_FEATURE
3764 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
3765 WLANBAP_ConfigType btAmpConfig;
3766 hdd_config_t *pConfig;
3767#endif
3768 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07003769 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003770
3771 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07003772 /*
3773 * cfg80211: wiphy allocation
3774 */
3775 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
3776
3777 if(wiphy == NULL)
3778 {
3779 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003780 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003781 }
3782
3783 pHddCtx = wiphy_priv(wiphy);
3784
Jeff Johnson295189b2012-06-20 16:38:30 -07003785 //Initialize the adapter context to zeros.
3786 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
3787
Jeff Johnson295189b2012-06-20 16:38:30 -07003788 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003789 hdd_prevent_suspend();
3790 pHddCtx->isLoadUnloadInProgress = TRUE;
3791
3792 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
3793
3794 /*Get vos context here bcoz vos_open requires it*/
3795 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
3796
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08003797 if(pVosContext == NULL)
3798 {
3799 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
3800 goto err_free_hdd_context;
3801 }
3802
Jeff Johnson295189b2012-06-20 16:38:30 -07003803 //Save the Global VOSS context in adapter context for future.
3804 pHddCtx->pvosContext = pVosContext;
3805
3806 //Save the adapter context in global context for future.
3807 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
3808
Jeff Johnson295189b2012-06-20 16:38:30 -07003809 pHddCtx->parent_dev = dev;
3810
3811 init_completion(&pHddCtx->full_pwr_comp_var);
3812 init_completion(&pHddCtx->standby_comp_var);
3813 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003814 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003815 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003816
3817 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
3818
3819 // Load all config first as TL config is needed during vos_open
3820 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
3821 if(pHddCtx->cfg_ini == NULL)
3822 {
3823 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
3824 goto err_free_hdd_context;
3825 }
3826
3827 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
3828
3829 // Read and parse the qcom_cfg.ini file
3830 status = hdd_parse_config_ini( pHddCtx );
3831 if ( VOS_STATUS_SUCCESS != status )
3832 {
3833 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
3834 __func__, WLAN_INI_FILE);
3835 goto err_config;
3836 }
3837
Jeff Johnson295189b2012-06-20 16:38:30 -07003838 /*
3839 * cfg80211: Initialization and registration ...
3840 */
3841 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
3842 {
3843 hddLog(VOS_TRACE_LEVEL_FATAL,
3844 "%s: wlan_hdd_cfg80211_register return failure", __func__);
3845 goto err_wiphy_reg;
3846 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003847
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003848 // Update VOS trace levels based upon the cfg.ini
3849 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
3850 pHddCtx->cfg_ini->vosTraceEnableBAP);
3851 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
3852 pHddCtx->cfg_ini->vosTraceEnableTL);
3853 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
3854 pHddCtx->cfg_ini->vosTraceEnableWDI);
3855 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
3856 pHddCtx->cfg_ini->vosTraceEnableHDD);
3857 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
3858 pHddCtx->cfg_ini->vosTraceEnableSME);
3859 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
3860 pHddCtx->cfg_ini->vosTraceEnablePE);
3861 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
3862 pHddCtx->cfg_ini->vosTraceEnableWDA);
3863 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
3864 pHddCtx->cfg_ini->vosTraceEnableSYS);
3865 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
3866 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003867 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
3868 pHddCtx->cfg_ini->vosTraceEnableSAP);
3869 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
3870 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003871
Jeff Johnson295189b2012-06-20 16:38:30 -07003872 // Update WDI trace levels based upon the cfg.ini
3873 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
3874 pHddCtx->cfg_ini->wdiTraceEnableDAL);
3875 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
3876 pHddCtx->cfg_ini->wdiTraceEnableCTL);
3877 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
3878 pHddCtx->cfg_ini->wdiTraceEnableDAT);
3879 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
3880 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003881
Jeff Johnson88ba7742013-02-27 14:36:02 -08003882 if (VOS_FTM_MODE == hdd_get_conparam())
3883 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003884 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
3885 {
3886 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
3887 goto err_free_hdd_context;
3888 }
3889 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
3890 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08003891 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003892
Jeff Johnson88ba7742013-02-27 14:36:02 -08003893 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07003894 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3895 {
3896 status = vos_watchdog_open(pVosContext,
3897 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
3898
3899 if(!VOS_IS_STATUS_SUCCESS( status ))
3900 {
3901 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003902 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07003903 }
3904 }
3905
3906 pHddCtx->isLogpInProgress = FALSE;
3907 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
3908
Jeff Johnson295189b2012-06-20 16:38:30 -07003909 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
3910 if(!VOS_IS_STATUS_SUCCESS(status))
3911 {
3912 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003913 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07003914 }
3915
Jeff Johnson295189b2012-06-20 16:38:30 -07003916 status = vos_open( &pVosContext, 0);
3917 if ( !VOS_IS_STATUS_SUCCESS( status ))
3918 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003919 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
3920 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07003921 }
3922
Jeff Johnson295189b2012-06-20 16:38:30 -07003923 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
3924
3925 if ( NULL == pHddCtx->hHal )
3926 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003927 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003928 goto err_vosclose;
3929 }
3930
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003931 status = vos_preStart( pHddCtx->pvosContext );
3932 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3933 {
3934 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
3935 goto err_vosclose;
3936 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003937
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003938 /* Note that the vos_preStart() sequence triggers the cfg download.
3939 The cfg download must occur before we update the SME config
3940 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07003941 status = hdd_set_sme_config( pHddCtx );
3942
3943 if ( VOS_STATUS_SUCCESS != status )
3944 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003945 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
3946 goto err_vosclose;
3947 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003948
3949 //Initialize the WMM module
3950 status = hdd_wmm_init(pHddCtx);
3951 if (!VOS_IS_STATUS_SUCCESS(status))
3952 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003953 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003954 goto err_vosclose;
3955 }
3956
Jeff Johnson295189b2012-06-20 16:38:30 -07003957 /* In the integrated architecture we update the configuration from
3958 the INI file and from NV before vOSS has been started so that
3959 the final contents are available to send down to the cCPU */
3960
3961 // Apply the cfg.ini to cfg.dat
3962 if (FALSE == hdd_update_config_dat(pHddCtx))
3963 {
3964 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
3965 goto err_vosclose;
3966 }
3967
3968 // Apply the NV to cfg.dat
3969 /* Prima Update MAC address only at here */
3970 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
3971 {
3972#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
3973 /* There was not a valid set of MAC Addresses in NV. See if the
3974 default addresses were modified by the cfg.ini settings. If so,
3975 we'll use them, but if not, we'll autogenerate a set of MAC
3976 addresses based upon the device serial number */
3977
3978 static const v_MACADDR_t default_address =
3979 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
3980 unsigned int serialno;
3981 int i;
3982
3983 serialno = wcnss_get_serial_number();
3984 if ((0 != serialno) &&
3985 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
3986 sizeof(default_address))))
3987 {
3988 /* cfg.ini has the default address, invoke autogen logic */
3989
3990 /* MAC address has 3 bytes of OUI so we have a maximum of 3
3991 bytes of the serial number that can be used to generate
3992 the other 3 bytes of the MAC address. Mask off all but
3993 the lower 3 bytes (this will also make sure we don't
3994 overflow in the next step) */
3995 serialno &= 0x00FFFFFF;
3996
3997 /* we need a unique address for each session */
3998 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
3999
4000 /* autogen all addresses */
4001 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4002 {
4003 /* start with the entire default address */
4004 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
4005 /* then replace the lower 3 bytes */
4006 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
4007 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
4008 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
4009
4010 serialno++;
4011 }
4012
4013 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
4014 MAC_ADDRESS_STR,
4015 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4016 }
4017 else
4018#endif //WLAN_AUTOGEN_MACADDR_FEATURE
4019 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004020 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004021 "%s: Invalid MAC address in NV, using MAC from ini file "
4022 MAC_ADDRESS_STR, __func__,
4023 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4024 }
4025 }
4026 {
4027 eHalStatus halStatus;
4028 // Set the MAC Address
4029 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
4030 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
4031 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
4032 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
4033
4034 if (!HAL_STATUS_SUCCESS( halStatus ))
4035 {
4036 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
4037 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08004038 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004039 }
4040 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004041
4042 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
4043 Note: Firmware image will be read and downloaded inside vos_start API */
4044 status = vos_start( pHddCtx->pvosContext );
4045 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4046 {
4047 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
4048 goto err_vosclose;
4049 }
4050
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004051 /* Exchange capability info between Host and FW and also get versioning info from FW */
4052 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004053
4054 status = hdd_post_voss_start_config( pHddCtx );
4055 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4056 {
4057 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
4058 __func__);
4059 goto err_vosstop;
4060 }
4061
Jeff Johnson295189b2012-06-20 16:38:30 -07004062 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4063 {
4064 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
4065 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4066 }
4067 else
4068 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004069 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
4070 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4071 if (pAdapter != NULL)
4072 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304073 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07004074 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304075 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
4076 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
4077 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07004078
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304079 /* Generate the P2P Device Address. This consists of the device's
4080 * primary MAC address with the locally administered bit set.
4081 */
4082 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07004083 }
4084 else
4085 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304086 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
4087 if (p2p_dev_addr != NULL)
4088 {
4089 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
4090 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
4091 }
4092 else
4093 {
4094 hddLog(VOS_TRACE_LEVEL_FATAL,
4095 "%s: Failed to allocate mac_address for p2p_device",
4096 __func__);
4097 goto err_close_adapter;
4098 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004099 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004100
4101 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
4102 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
4103 if ( NULL == pP2pAdapter )
4104 {
4105 hddLog(VOS_TRACE_LEVEL_FATAL,
4106 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004107 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004108 goto err_close_adapter;
4109 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004110 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004111 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004112
4113 if( pAdapter == NULL )
4114 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004115 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
4116 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004117 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004118
Jeff Johnson295189b2012-06-20 16:38:30 -07004119#ifdef WLAN_BTAMP_FEATURE
4120 vStatus = WLANBAP_Open(pVosContext);
4121 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4122 {
4123 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4124 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004125 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004126 }
4127
4128 vStatus = BSL_Init(pVosContext);
4129 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4130 {
4131 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4132 "%s: Failed to Init BSL",__func__);
4133 goto err_bap_close;
4134 }
4135 vStatus = WLANBAP_Start(pVosContext);
4136 if (!VOS_IS_STATUS_SUCCESS(vStatus))
4137 {
4138 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4139 "%s: Failed to start TL",__func__);
4140 goto err_bap_close;
4141 }
4142
4143 pConfig = pHddCtx->cfg_ini;
4144 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
4145 status = WLANBAP_SetConfig(&btAmpConfig);
4146
4147#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07004148
Jeff Johnson295189b2012-06-20 16:38:30 -07004149#ifdef FEATURE_WLAN_SCAN_PNO
4150 /*SME must send channel update configuration to RIVA*/
4151 sme_UpdateChannelConfig(pHddCtx->hHal);
4152#endif
4153
Jeff Johnson295189b2012-06-20 16:38:30 -07004154 /* Register with platform driver as client for Suspend/Resume */
4155 status = hddRegisterPmOps(pHddCtx);
4156 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4157 {
4158 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
4159#ifdef WLAN_BTAMP_FEATURE
4160 goto err_bap_stop;
4161#else
Jeff Johnsone7245742012-09-05 17:12:55 -07004162 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004163#endif //WLAN_BTAMP_FEATURE
4164 }
4165
4166 /* Register TM level change handler function to the platform */
4167 status = hddDevTmRegisterNotifyCallback(pHddCtx);
4168 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4169 {
4170 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
4171 goto err_unregister_pmops;
4172 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004173
4174 /* register for riva power on lock to platform driver */
4175 if (req_riva_power_on_lock("wlan"))
4176 {
4177 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
4178 __func__);
4179 goto err_unregister_pmops;
4180 }
4181
Jeff Johnson295189b2012-06-20 16:38:30 -07004182 // register net device notifier for device change notification
4183 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4184
4185 if(ret < 0)
4186 {
4187 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
4188 goto err_free_power_on_lock;
4189 }
4190
4191 //Initialize the nlink service
4192 if(nl_srv_init() != 0)
4193 {
4194 hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
4195 goto err_reg_netdev;
4196 }
4197
4198 //Initialize the BTC service
4199 if(btc_activate_service(pHddCtx) != 0)
4200 {
4201 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
4202 goto err_nl_srv;
4203 }
4204
4205#ifdef PTT_SOCK_SVC_ENABLE
4206 //Initialize the PTT service
4207 if(ptt_sock_activate_svc(pHddCtx) != 0)
4208 {
4209 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
4210 goto err_nl_srv;
4211 }
4212#endif
4213
Jeff Johnson295189b2012-06-20 16:38:30 -07004214 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004215 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004216 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07004217 /* Action frame registered in one adapter which will
4218 * applicable to all interfaces
4219 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07004220 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07004221 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004222
4223 mutex_init(&pHddCtx->sap_lock);
4224
4225 pHddCtx->isLoadUnloadInProgress = FALSE;
4226
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004227#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004228#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4229 /* Initialize the wake lcok */
4230 wake_lock_init(&pHddCtx->rx_wake_lock,
4231 WAKE_LOCK_SUSPEND,
4232 "qcom_rx_wakelock");
4233#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004234 /* Initialize the wake lcok */
4235 wake_lock_init(&pHddCtx->sap_wake_lock,
4236 WAKE_LOCK_SUSPEND,
4237 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004238#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004239
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004240 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
4241 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07004242
4243 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4244 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004245
4246 // Initialize the restart logic
4247 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05304248
Jeff Johnson295189b2012-06-20 16:38:30 -07004249 goto success;
4250
4251err_nl_srv:
4252 nl_srv_exit();
4253
4254err_reg_netdev:
4255 unregister_netdevice_notifier(&hdd_netdev_notifier);
4256
4257err_free_power_on_lock:
4258 free_riva_power_on_lock("wlan");
4259
4260err_unregister_pmops:
4261 hddDevTmUnregisterNotifyCallback(pHddCtx);
4262 hddDeregisterPmOps(pHddCtx);
4263
4264#ifdef WLAN_BTAMP_FEATURE
4265err_bap_stop:
4266 WLANBAP_Stop(pVosContext);
4267#endif
4268
4269#ifdef WLAN_BTAMP_FEATURE
4270err_bap_close:
4271 WLANBAP_Close(pVosContext);
4272#endif
4273
Jeff Johnson295189b2012-06-20 16:38:30 -07004274err_close_adapter:
4275 hdd_close_all_adapters( pHddCtx );
4276
4277err_vosstop:
4278 vos_stop(pVosContext);
4279
4280err_vosclose:
4281 status = vos_sched_close( pVosContext );
4282 if (!VOS_IS_STATUS_SUCCESS(status)) {
4283 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4284 "%s: Failed to close VOSS Scheduler", __func__);
4285 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
4286 }
4287 vos_close(pVosContext );
4288
Jeff Johnson295189b2012-06-20 16:38:30 -07004289err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004290 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004291
4292err_wdclose:
4293 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4294 vos_watchdog_close(pVosContext);
4295
Jeff Johnson295189b2012-06-20 16:38:30 -07004296err_wiphy_reg:
4297 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004298
4299err_config:
4300 kfree(pHddCtx->cfg_ini);
4301 pHddCtx->cfg_ini= NULL;
4302
4303err_free_hdd_context:
4304 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004305 wiphy_free(wiphy) ;
4306 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004307 VOS_BUG(1);
4308
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08004309 if (hdd_is_ssr_required())
4310 {
4311 /* WDI timeout had happened during load, so SSR is needed here */
4312 subsystem_restart("wcnss");
4313 msleep(5000);
4314 }
4315 hdd_set_ssr_required (VOS_FALSE);
4316
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004317 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004318
4319success:
4320 EXIT();
4321 return 0;
4322}
4323
4324/**---------------------------------------------------------------------------
4325
Jeff Johnson32d95a32012-09-10 13:15:23 -07004326 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07004327
Jeff Johnson32d95a32012-09-10 13:15:23 -07004328 This is the driver entry point - called in different timeline depending
4329 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07004330
4331 \param - None
4332
4333 \return - 0 for success, non zero for failure
4334
4335 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07004336static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004337{
4338 VOS_STATUS status;
4339 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004340 struct device *dev = NULL;
4341 int ret_status = 0;
4342
4343 ENTER();
4344
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004345#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004346 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07004347#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004348
4349 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
4350 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
4351
4352 //Power Up Libra WLAN card first if not already powered up
4353 status = vos_chipPowerUp(NULL,NULL,NULL);
4354 if (!VOS_IS_STATUS_SUCCESS(status))
4355 {
4356 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
4357 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004358 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004359 }
4360
Jeff Johnson295189b2012-06-20 16:38:30 -07004361#ifdef ANI_BUS_TYPE_PCI
4362
4363 dev = wcnss_wlan_get_device();
4364
4365#endif // ANI_BUS_TYPE_PCI
4366
4367#ifdef ANI_BUS_TYPE_PLATFORM
4368 dev = wcnss_wlan_get_device();
4369#endif // ANI_BUS_TYPE_PLATFORM
4370
4371
4372 do {
4373 if (NULL == dev) {
4374 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
4375 ret_status = -1;
4376 break;
4377 }
4378
4379#ifdef MEMORY_DEBUG
4380 vos_mem_init();
4381#endif
4382
4383#ifdef TIMER_MANAGER
4384 vos_timer_manager_init();
4385#endif
4386
4387 /* Preopen VOSS so that it is ready to start at least SAL */
4388 status = vos_preOpen(&pVosContext);
4389
4390 if (!VOS_IS_STATUS_SUCCESS(status))
4391 {
4392 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
4393 ret_status = -1;
4394 break;
4395 }
4396
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004397#ifndef MODULE
4398 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
4399 */
4400 hdd_set_conparam((v_UINT_t)con_mode);
4401#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004402
4403 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004404 if (hdd_wlan_startup(dev))
4405 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004406 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004407 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004408 vos_preClose( &pVosContext );
4409 ret_status = -1;
4410 break;
4411 }
4412
4413 /* Cancel the vote for XO Core ON
4414 * This is done here for safety purposes in case we re-initialize without turning
4415 * it OFF in any error scenario.
4416 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004417 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07004418 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004419 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07004420 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4421 {
4422 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
4423 " Power consumed will be high\n");
4424 }
4425 } while (0);
4426
4427 if (0 != ret_status)
4428 {
4429 //Assert Deep sleep signal now to put Libra HW in lowest power state
4430 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4431 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
4432
4433 //Vote off any PMIC voltage supplies
4434 vos_chipPowerDown(NULL, NULL, NULL);
4435#ifdef TIMER_MANAGER
4436 vos_timer_exit();
4437#endif
4438#ifdef MEMORY_DEBUG
4439 vos_mem_exit();
4440#endif
4441
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004442#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004443 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004444#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004445 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
4446 }
4447 else
4448 {
4449 //Send WLAN UP indication to Nlink Service
4450 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
4451
4452 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
4453
4454 }
4455
4456 EXIT();
4457
4458 return ret_status;
4459}
4460
Jeff Johnson32d95a32012-09-10 13:15:23 -07004461/**---------------------------------------------------------------------------
4462
4463 \brief hdd_module_init() - Init Function
4464
4465 This is the driver entry point (invoked when module is loaded using insmod)
4466
4467 \param - None
4468
4469 \return - 0 for success, non zero for failure
4470
4471 --------------------------------------------------------------------------*/
4472#ifdef MODULE
4473static int __init hdd_module_init ( void)
4474{
4475 return hdd_driver_init();
4476}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004477#else /* #ifdef MODULE */
4478static int __init hdd_module_init ( void)
4479{
4480 /* Driver initialization is delayed to fwpath_changed_handler */
4481 return 0;
4482}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004483#endif /* #ifdef MODULE */
4484
Jeff Johnson295189b2012-06-20 16:38:30 -07004485
4486/**---------------------------------------------------------------------------
4487
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004488 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07004489
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004490 This is the driver exit point (invoked when module is unloaded using rmmod
4491 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07004492
4493 \param - None
4494
4495 \return - None
4496
4497 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004498static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004499{
4500 hdd_context_t *pHddCtx = NULL;
4501 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004502
4503 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
4504
4505 //Get the global vos context
4506 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4507
4508 if(!pVosContext)
4509 {
4510 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
4511 goto done;
4512 }
4513
4514 //Get the HDD context.
4515 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
4516
4517 if(!pHddCtx)
4518 {
4519 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
4520 }
4521 else
4522 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004523 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07004524 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07004525 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
4526 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07004527 }
4528
4529 pHddCtx->isLoadUnloadInProgress = TRUE;
4530 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4531
4532 //Do all the cleanup before deregistering the driver
4533 hdd_wlan_exit(pHddCtx);
4534 }
4535
Jeff Johnson295189b2012-06-20 16:38:30 -07004536 vos_preClose( &pVosContext );
4537
4538#ifdef TIMER_MANAGER
4539 vos_timer_exit();
4540#endif
4541#ifdef MEMORY_DEBUG
4542 vos_mem_exit();
4543#endif
4544
4545done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004546#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004547 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004548#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004549 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
4550}
4551
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004552/**---------------------------------------------------------------------------
4553
4554 \brief hdd_module_exit() - Exit function
4555
4556 This is the driver exit point (invoked when module is unloaded using rmmod)
4557
4558 \param - None
4559
4560 \return - None
4561
4562 --------------------------------------------------------------------------*/
4563static void __exit hdd_module_exit(void)
4564{
4565 hdd_driver_exit();
4566}
4567
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004568#ifdef MODULE
4569static int fwpath_changed_handler(const char *kmessage,
4570 struct kernel_param *kp)
4571{
4572 /* nothing to do when driver is DLKM */
4573 return 0;
4574}
4575
4576static int con_mode_handler(const char *kmessage,
4577 struct kernel_param *kp)
4578{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07004579 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004580}
4581#else /* #ifdef MODULE */
4582/**---------------------------------------------------------------------------
4583
4584 \brief fwpath_changed_handler() - Handler Function
4585
4586 This is the driver entry point
4587 - delayed driver initialization when driver is statically linked
4588 - invoked when module parameter fwpath is modified from userpspace to signal
4589 initializing the WLAN driver
4590
4591 \return - 0 for success, non zero for failure
4592
4593 --------------------------------------------------------------------------*/
4594static int fwpath_changed_handler(const char *kmessage,
4595 struct kernel_param *kp)
4596{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004597 int ret_status;
4598
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004599 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004600 ret_status = hdd_driver_init();
4601 wlan_hdd_inited = ret_status ? 0 : 1;
4602 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004603 }
4604
4605 hdd_driver_exit();
4606
4607 msleep(200);
4608
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004609 ret_status = hdd_driver_init();
4610 wlan_hdd_inited = ret_status ? 0 : 1;
4611 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004612}
4613
Jeff Johnson295189b2012-06-20 16:38:30 -07004614/**---------------------------------------------------------------------------
4615
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004616 \brief con_mode_handler() -
4617
4618 Handler function for module param con_mode when it is changed by userspace
4619 Dynamically linked - do nothing
4620 Statically linked - exit and init driver, as in rmmod and insmod
4621
4622 \param -
4623
4624 \return -
4625
4626 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004627static int con_mode_handler(const char *kmessage,
4628 struct kernel_param *kp)
4629{
4630 int ret = param_set_int(kmessage, kp);
4631
4632 if (ret)
4633 return ret;
4634
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004635 return fwpath_changed_handler(kmessage, kp);
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004636}
4637#endif /* #ifdef MODULE */
4638
4639/**---------------------------------------------------------------------------
4640
Jeff Johnson295189b2012-06-20 16:38:30 -07004641 \brief hdd_get_conparam() -
4642
4643 This is the driver exit point (invoked when module is unloaded using rmmod)
4644
4645 \param - None
4646
4647 \return - tVOS_CON_MODE
4648
4649 --------------------------------------------------------------------------*/
4650tVOS_CON_MODE hdd_get_conparam ( void )
4651{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004652#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07004653 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004654#else
4655 return (tVOS_CON_MODE)curr_con_mode;
4656#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004657}
4658void hdd_set_conparam ( v_UINT_t newParam )
4659{
4660 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004661#ifndef MODULE
4662 curr_con_mode = con_mode;
4663#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004664}
4665/**---------------------------------------------------------------------------
4666
4667 \brief hdd_softap_sta_deauth() - function
4668
4669 This to take counter measure to handle deauth req from HDD
4670
4671 \param - pAdapter - Pointer to the HDD
4672
4673 \param - enable - boolean value
4674
4675 \return - None
4676
4677 --------------------------------------------------------------------------*/
4678
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004679VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07004680{
Jeff Johnson295189b2012-06-20 16:38:30 -07004681 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004682 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07004683
4684 ENTER();
4685
4686 hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4687
4688 //Ignore request to deauth bcmc station
4689 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004690 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004691
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004692 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07004693
4694 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004695 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004696}
4697
4698/**---------------------------------------------------------------------------
4699
4700 \brief hdd_softap_sta_disassoc() - function
4701
4702 This to take counter measure to handle deauth req from HDD
4703
4704 \param - pAdapter - Pointer to the HDD
4705
4706 \param - enable - boolean value
4707
4708 \return - None
4709
4710 --------------------------------------------------------------------------*/
4711
4712void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
4713{
4714 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4715
4716 ENTER();
4717
4718 hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4719
4720 //Ignore request to disassoc bcmc station
4721 if( pDestMacAddress[0] & 0x1 )
4722 return;
4723
4724 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
4725}
4726
4727void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
4728{
4729 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4730
4731 ENTER();
4732
4733 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4734
4735 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
4736}
4737
Jeff Johnson295189b2012-06-20 16:38:30 -07004738/**---------------------------------------------------------------------------
4739 *
4740 * \brief hdd_get__concurrency_mode() -
4741 *
4742 *
4743 * \param - None
4744 *
4745 * \return - CONCURRENCY MODE
4746 *
4747 * --------------------------------------------------------------------------*/
4748tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
4749{
4750 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
4751 hdd_context_t *pHddCtx;
4752
4753 if (NULL != pVosContext)
4754 {
4755 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
4756 if (NULL != pHddCtx)
4757 {
4758 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
4759 }
4760 }
4761
4762 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004763 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004764 return VOS_STA;
4765}
4766
4767/* Decide whether to allow/not the apps power collapse.
4768 * Allow apps power collapse if we are in connected state.
4769 * if not, allow only if we are in IMPS */
4770v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
4771{
4772 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08004773 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08004774 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07004775 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4776 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4777 hdd_adapter_t *pAdapter = NULL;
4778 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08004779 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004780
Jeff Johnson295189b2012-06-20 16:38:30 -07004781 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4782 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004783
Yathish9f22e662012-12-10 14:21:35 -08004784 concurrent_state = hdd_get_concurrency_mode();
4785
4786#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4787 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
4788 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
4789 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
4790 return TRUE;
4791#endif
4792
Jeff Johnson295189b2012-06-20 16:38:30 -07004793 /*loop through all adapters. TBD fix for Concurrency */
4794 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4795 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4796 {
4797 pAdapter = pAdapterNode->pAdapter;
4798 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4799 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4800 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08004801 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07004802 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08004803 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08004804 (eANI_BOOLEAN_TRUE == scanRspPending) ||
4805 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07004806 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08004807 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08004808 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
4809 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07004810 return FALSE;
4811 }
4812 }
4813 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4814 pAdapterNode = pNext;
4815 }
4816 return TRUE;
4817}
4818
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08004819/* Decides whether to send suspend notification to Riva
4820 * if any adapter is in BMPS; then it is required */
4821v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
4822{
4823 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
4824 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4825
4826 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
4827 {
4828 return TRUE;
4829 }
4830 return FALSE;
4831}
4832
Jeff Johnson295189b2012-06-20 16:38:30 -07004833void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
4834{
4835 switch(mode)
4836 {
4837 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07004838 case WLAN_HDD_P2P_CLIENT:
4839 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004840 case WLAN_HDD_SOFTAP:
Jeff Johnsone7245742012-09-05 17:12:55 -07004841 pHddCtx->concurrency_mode |= (1 << mode);
4842 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07004843 break;
4844 default:
4845 break;
4846
4847 }
4848 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
4849 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
4850}
4851
4852
4853void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
4854{
4855 switch(mode)
4856 {
4857 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07004858 case WLAN_HDD_P2P_CLIENT:
4859 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004860 case WLAN_HDD_SOFTAP:
4861 pHddCtx->no_of_sessions[mode]--;
4862 if (!(pHddCtx->no_of_sessions[mode]))
4863 pHddCtx->concurrency_mode &= (~(1 << mode));
4864 break;
4865 default:
4866 break;
4867 }
4868 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
4869 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
4870}
4871
Jeff Johnsone7245742012-09-05 17:12:55 -07004872/**---------------------------------------------------------------------------
4873 *
4874 * \brief wlan_hdd_restart_init
4875 *
4876 * This function initalizes restart timer/flag. An internal function.
4877 *
4878 * \param - pHddCtx
4879 *
4880 * \return - None
4881 *
4882 * --------------------------------------------------------------------------*/
4883
4884static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
4885{
4886 /* Initialize */
4887 pHddCtx->hdd_restart_retries = 0;
4888 atomic_set(&pHddCtx->isRestartInProgress, 0);
4889 vos_timer_init(&pHddCtx->hdd_restart_timer,
4890 VOS_TIMER_TYPE_SW,
4891 wlan_hdd_restart_timer_cb,
4892 pHddCtx);
4893}
4894/**---------------------------------------------------------------------------
4895 *
4896 * \brief wlan_hdd_restart_deinit
4897 *
4898 * This function cleans up the resources used. An internal function.
4899 *
4900 * \param - pHddCtx
4901 *
4902 * \return - None
4903 *
4904 * --------------------------------------------------------------------------*/
4905
4906static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
4907{
4908
4909 VOS_STATUS vos_status;
4910 /* Block any further calls */
4911 atomic_set(&pHddCtx->isRestartInProgress, 1);
4912 /* Cleanup */
4913 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
4914 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004915 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07004916 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
4917 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004918 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07004919
4920}
4921
4922/**---------------------------------------------------------------------------
4923 *
4924 * \brief wlan_hdd_framework_restart
4925 *
4926 * This function uses a cfg80211 API to start a framework initiated WLAN
4927 * driver module unload/load.
4928 *
4929 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
4930 *
4931 *
4932 * \param - pHddCtx
4933 *
4934 * \return - VOS_STATUS_SUCCESS: Success
4935 * VOS_STATUS_E_EMPTY: Adapter is Empty
4936 * VOS_STATUS_E_NOMEM: No memory
4937
4938 * --------------------------------------------------------------------------*/
4939
4940static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
4941{
4942 VOS_STATUS status = VOS_STATUS_SUCCESS;
4943 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4944 int len = (sizeof (struct ieee80211_mgmt));
4945 struct ieee80211_mgmt *mgmt = NULL;
4946
4947 /* Prepare the DEAUTH managment frame with reason code */
4948 mgmt = kzalloc(len, GFP_KERNEL);
4949 if(mgmt == NULL)
4950 {
4951 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1250df42012-12-10 14:31:52 -08004952 "%s: memory allocation failed (%d bytes)", __func__, len);
Jeff Johnsone7245742012-09-05 17:12:55 -07004953 return VOS_STATUS_E_NOMEM;
4954 }
4955 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
4956
4957 /* Iterate over all adapters/devices */
4958 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4959 do
4960 {
4961 if( (status == VOS_STATUS_SUCCESS) &&
4962 pAdapterNode &&
4963 pAdapterNode->pAdapter)
4964 {
4965 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4966 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
4967 pAdapterNode->pAdapter->dev->name,
4968 pAdapterNode->pAdapter->device_mode,
4969 pHddCtx->hdd_restart_retries + 1);
4970 /*
4971 * CFG80211 event to restart the driver
4972 *
4973 * 'cfg80211_send_unprot_deauth' sends a
4974 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
4975 * of SME(Linux Kernel) state machine.
4976 *
4977 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
4978 * the driver.
4979 *
4980 */
4981
4982 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
4983 }
4984 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4985 pAdapterNode = pNext;
4986 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
4987
4988
4989 /* Free the allocated management frame */
4990 kfree(mgmt);
4991
4992 /* Retry until we unload or reach max count */
4993 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
4994 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
4995
4996 return status;
4997
4998}
4999/**---------------------------------------------------------------------------
5000 *
5001 * \brief wlan_hdd_restart_timer_cb
5002 *
5003 * Restart timer callback. An internal function.
5004 *
5005 * \param - User data:
5006 *
5007 * \return - None
5008 *
5009 * --------------------------------------------------------------------------*/
5010
5011void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
5012{
5013 hdd_context_t *pHddCtx = usrDataForCallback;
5014 wlan_hdd_framework_restart(pHddCtx);
5015 return;
5016
5017}
5018
5019
5020/**---------------------------------------------------------------------------
5021 *
5022 * \brief wlan_hdd_restart_driver
5023 *
5024 * This function sends an event to supplicant to restart the WLAN driver.
5025 *
5026 * This function is called from vos_wlanRestart.
5027 *
5028 * \param - pHddCtx
5029 *
5030 * \return - VOS_STATUS_SUCCESS: Success
5031 * VOS_STATUS_E_EMPTY: Adapter is Empty
5032 * VOS_STATUS_E_ALREADY: Request already in progress
5033
5034 * --------------------------------------------------------------------------*/
5035VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
5036{
5037 VOS_STATUS status = VOS_STATUS_SUCCESS;
5038
5039 /* A tight check to make sure reentrancy */
5040 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
5041 {
5042 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
5043 "%s: WLAN restart is already in progress", __func__);
5044
5045 return VOS_STATUS_E_ALREADY;
5046 }
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005047 /* when WLAN driver is statically linked, then invoke SSR by sending
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005048 * the reset interrupt. If it is DLKM, then use restart API
5049 */
5050#ifdef MODULE
Jeff Johnsone7245742012-09-05 17:12:55 -07005051 status = wlan_hdd_framework_restart(pHddCtx);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005052#else
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005053#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005054 wcnss_reset_intr();
5055#endif
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005056#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005057
Jeff Johnsone7245742012-09-05 17:12:55 -07005058 return status;
5059}
5060
5061
Jeff Johnson295189b2012-06-20 16:38:30 -07005062//Register the module init/exit functions
5063module_init(hdd_module_init);
5064module_exit(hdd_module_exit);
5065
5066MODULE_LICENSE("Dual BSD/GPL");
5067MODULE_AUTHOR("Qualcomm Atheros, Inc.");
5068MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
5069
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005070module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
5071 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07005072
5073module_param_call(fwpath, fwpath_changed_handler, param_get_string, fwpath,
5074 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);