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