blob: a25777991be6266d4520a357b14594815fba0bc1 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/*========================================================================
43
44 \file wlan_hdd_main.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
54/**=========================================================================
55
56 EDIT HISTORY FOR FILE
57
58
59 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
61
62
63 $Header:$ $DateTime: $ $Author: $
64
65
66 when who what, where, why
67 -------- --- --------------------------------------------------------
68 04/5/09 Shailender Created module.
69 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
70 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
71 ==========================================================================*/
72
73/*--------------------------------------------------------------------------
74 Include Files
75 ------------------------------------------------------------------------*/
76//#include <wlan_qct_driver.h>
77#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070078#include <vos_api.h>
79#include <vos_sched.h>
80#include <vos_power.h>
81#include <linux/etherdevice.h>
82#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070083#ifdef ANI_BUS_TYPE_PLATFORM
84#include <linux/wcnss_wlan.h>
85#endif //ANI_BUS_TYPE_PLATFORM
86#ifdef ANI_BUS_TYPE_PCI
87#include "wcnss_wlan.h"
88#endif /* ANI_BUS_TYPE_PCI */
89#include <wlan_hdd_tx_rx.h>
90#include <palTimer.h>
91#include <wniApi.h>
92#include <wlan_nlink_srv.h>
93#include <wlan_btc_svc.h>
94#include <wlan_hdd_cfg.h>
95#include <wlan_ptt_sock_svc.h>
96#include <wlan_hdd_wowl.h>
97#include <wlan_hdd_misc.h>
98#include <wlan_hdd_wext.h>
99#ifdef WLAN_BTAMP_FEATURE
100#include <bap_hdd_main.h>
101#include <bapInternal.h>
102#endif // WLAN_BTAMP_FEATURE
103
Jeff Johnson295189b2012-06-20 16:38:30 -0700104#include <linux/wireless.h>
105#include <net/cfg80211.h>
106#include "wlan_hdd_cfg80211.h"
107#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700108#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700109int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include "sapApi.h"
111#include <linux/semaphore.h>
112#include <mach/subsystem_restart.h>
113#include <wlan_hdd_hostapd.h>
114#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700115#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700116#include "wlan_hdd_dev_pwr.h"
117#ifdef WLAN_BTAMP_FEATURE
118#include "bap_hdd_misc.h"
119#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700120#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700121#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800122#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530123#ifdef FEATURE_WLAN_TDLS
124#include "wlan_hdd_tdls.h"
125#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700126
127#ifdef MODULE
128#define WLAN_MODULE_NAME module_name(THIS_MODULE)
129#else
130#define WLAN_MODULE_NAME "wlan"
131#endif
132
133#ifdef TIMER_MANAGER
134#define TIMER_MANAGER_STR " +TIMER_MANAGER"
135#else
136#define TIMER_MANAGER_STR ""
137#endif
138
139#ifdef MEMORY_DEBUG
140#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
141#else
142#define MEMORY_DEBUG_STR ""
143#endif
144
145/* the Android framework expects this param even though we don't use it */
146#define BUF_LEN 20
147static char fwpath[BUF_LEN];
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700148#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700149static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700150#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700151
Jeff Johnsone7245742012-09-05 17:12:55 -0700152/*
153 * The rate at which the driver sends RESTART event to supplicant
154 * once the function 'vos_wlanRestart()' is called
155 *
156 */
157#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
158#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800159#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700160static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700161#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700162/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700163static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700164
165//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700166static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
167static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
168static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
169void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800170void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700171
Jeff Johnson295189b2012-06-20 16:38:30 -0700172v_U16_t hdd_select_queue(struct net_device *dev,
173 struct sk_buff *skb);
174
175#ifdef WLAN_FEATURE_PACKET_FILTERING
176static void hdd_set_multicast_list(struct net_device *dev);
177#endif
178
179void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
180
181extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800182#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
183void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
184static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
185static VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
186#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700187static int hdd_netdev_notifier_call(struct notifier_block * nb,
188 unsigned long state,
189 void *ndev)
190{
191 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700192 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
193 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -0700194#ifdef WLAN_BTAMP_FEATURE
195 VOS_STATUS status;
196 hdd_context_t *pHddCtx;
197#endif
198
199 //Make sure that this callback corresponds to our device.
200 if((strncmp( dev->name, "wlan", 4 )) &&
Jeff Johnsone7245742012-09-05 17:12:55 -0700201 (strncmp( dev->name, "p2p", 3))
Jeff Johnson295189b2012-06-20 16:38:30 -0700202 )
203 return NOTIFY_DONE;
204
Jeff Johnson295189b2012-06-20 16:38:30 -0700205 if (!dev->ieee80211_ptr)
206 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700207
Jeff Johnson295189b2012-06-20 16:38:30 -0700208
209 if(NULL == pAdapter)
210 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800211 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700212 VOS_ASSERT(0);
213 return NOTIFY_DONE;
214 }
215
216 hddLog(VOS_TRACE_LEVEL_INFO,"%s: New Net Device State = %lu", __func__, state);
217
218 switch (state) {
219 case NETDEV_REGISTER:
220 break;
221
222 case NETDEV_UNREGISTER:
223 break;
224
225 case NETDEV_UP:
226 break;
227
228 case NETDEV_DOWN:
229 break;
230
231 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700232 if(TRUE == pAdapter->isLinkUpSvcNeeded)
233 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700234 break;
235
236 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700237 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700238 {
239 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800240 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700241 hdd_abort_mac_scan(pAdapter->pHddCtx);
242 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800243 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700244 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
245 if(!result)
246 {
247 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800248 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700249 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700250 }
251 }
252 else
253 {
254 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700255 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700256 }
257#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700258 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700259 status = WLANBAP_StopAmp();
260 if(VOS_STATUS_SUCCESS != status )
261 {
262 pHddCtx->isAmpAllowed = VOS_TRUE;
263 hddLog(VOS_TRACE_LEVEL_FATAL,
264 "%s: Failed to stop AMP", __func__);
265 }
266 else
267 {
268 //a state m/c implementation in PAL is TBD to avoid this delay
269 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700270 if ( pHddCtx->isAmpAllowed )
271 {
272 WLANBAP_DeregisterFromHCI();
273 pHddCtx->isAmpAllowed = VOS_FALSE;
274 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700275 }
276#endif //WLAN_BTAMP_FEATURE
277 break;
278
279 default:
280 break;
281 }
282
283 return NOTIFY_DONE;
284}
285
286struct notifier_block hdd_netdev_notifier = {
287 .notifier_call = hdd_netdev_notifier_call,
288};
289
290/*---------------------------------------------------------------------------
291 * Function definitions
292 *-------------------------------------------------------------------------*/
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800293int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700294void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
295void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700296//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700297static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700298#ifndef MODULE
299/* current con_mode - used only for statically linked driver
300 * con_mode is changed by userspace to indicate a mode change which will
301 * result in calling the module exit and init functions. The module
302 * exit function will clean up based on the value of con_mode prior to it
303 * being changed by userspace. So curr_con_mode records the current con_mode
304 * for exit when con_mode becomes the next mode for init
305 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700306static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700307#endif
308
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800309/**---------------------------------------------------------------------------
310
311 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
312
313 Called immediately after the cfg.ini is read in order to configure
314 the desired trace levels.
315
316 \param - moduleId - module whose trace level is being configured
317 \param - bitmask - bitmask of log levels to be enabled
318
319 \return - void
320
321 --------------------------------------------------------------------------*/
322static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
323{
324 wpt_tracelevel level;
325
326 /* if the bitmask is the default value, then a bitmask was not
327 specified in cfg.ini, so leave the logging level alone (it
328 will remain at the "compiled in" default value) */
329 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
330 {
331 return;
332 }
333
334 /* a mask was specified. start by disabling all logging */
335 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
336
337 /* now cycle through the bitmask until all "set" bits are serviced */
338 level = VOS_TRACE_LEVEL_FATAL;
339 while (0 != bitmask)
340 {
341 if (bitmask & 1)
342 {
343 vos_trace_setValue(moduleId, level, 1);
344 }
345 level++;
346 bitmask >>= 1;
347 }
348}
349
350
Jeff Johnson295189b2012-06-20 16:38:30 -0700351/**---------------------------------------------------------------------------
352
353 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
354
355 Called immediately after the cfg.ini is read in order to configure
356 the desired trace levels in the WDI.
357
358 \param - moduleId - module whose trace level is being configured
359 \param - bitmask - bitmask of log levels to be enabled
360
361 \return - void
362
363 --------------------------------------------------------------------------*/
364static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
365{
366 wpt_tracelevel level;
367
368 /* if the bitmask is the default value, then a bitmask was not
369 specified in cfg.ini, so leave the logging level alone (it
370 will remain at the "compiled in" default value) */
371 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
372 {
373 return;
374 }
375
376 /* a mask was specified. start by disabling all logging */
377 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
378
379 /* now cycle through the bitmask until all "set" bits are serviced */
380 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
381 while (0 != bitmask)
382 {
383 if (bitmask & 1)
384 {
385 wpalTraceSetLevel(moduleId, level, 1);
386 }
387 level++;
388 bitmask >>= 1;
389 }
390}
Jeff Johnson295189b2012-06-20 16:38:30 -0700391
392int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
393{
394 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
395 hdd_priv_data_t priv_data;
396 tANI_U8 *command = NULL;
397 int ret = 0;
398
399 if (NULL == pAdapter)
400 {
401 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700402 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700403 ret = -ENODEV;
404 goto exit;
405 }
406
Jeff Johnsone7245742012-09-05 17:12:55 -0700407 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700408 {
409 ret = -EINVAL;
410 goto exit;
411 }
412
413 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
414 {
415 ret = -EFAULT;
416 goto exit;
417 }
418
419 command = kmalloc(priv_data.total_len, GFP_KERNEL);
420 if (!command)
421 {
422 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700423 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700424 ret = -ENOMEM;
425 goto exit;
426 }
427
428 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
429 {
430 ret = -EFAULT;
431 goto exit;
432 }
433
434 if ((SIOCDEVPRIVATE + 1) == cmd)
435 {
436 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
437
438 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700439 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700440
441 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
442 {
443 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
444 sizeof(tSirMacAddr)))
445 {
446 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700447 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700448 ret = -EFAULT;
449 }
450 }
Amar Singhal0974e402013-02-12 14:27:46 -0800451 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700452 {
Amar Singhal0974e402013-02-12 14:27:46 -0800453 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700454 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800455
Jeff Johnson295189b2012-06-20 16:38:30 -0700456 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800457
458 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700459 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700460 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800461 "%s: SetBandCommand Info comm %s UL %d, TL %d", __func__, command, priv_data.used_len, priv_data.total_len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700462 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800463 ret = hdd_setBand_helper(dev, ptr);
464 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700465 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
466 {
467 char *country_code;
468
469 country_code = command + 8;
470 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
471 pAdapter, pHddCtx->pvosContext);
472 if( 0 != ret )
473 {
474 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
475 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
476
477 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700478 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800479#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
480 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
481 {
482 tANI_U8 *value = command;
483 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
484 tANI_U8 revision = 0;
485 eHalStatus status = eHAL_STATUS_SUCCESS;
486 v_REGDOMAIN_t regId;
487
488 status = hdd_parse_countryrev(value, countryCode, &revision);
489 if (eHAL_STATUS_SUCCESS != status)
490 {
491 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
492 "%s: Failed to parse country revision information", __func__);
493 ret = -EINVAL;
494 goto exit;
495 }
496
497 /* Validate country code */
498 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
499 if (eHAL_STATUS_SUCCESS != status)
500 {
501 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
502 "%s: Invalid country code %s", __func__, countryCode);
503 ret = -EINVAL;
504 goto exit;
505 }
506
507 /* Validate revision */
508 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
509 {
510 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
511 "%s: Invalid revision %d", __func__, revision);
512 ret = -EINVAL;
513 goto exit;
514 }
515
516 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
517 pAdapter, pHddCtx->pvosContext);
518 if (0 != ret)
519 {
520 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
521 "%s: SME Change Country code fail ret=%d", __func__, ret);
522 ret = -EINVAL;
523 goto exit;
524 }
525
526 if (0 == strncmp(countryCode, "KR", 2))
527 {
528 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
529 revision);
530 if (eHAL_STATUS_SUCCESS != status)
531 {
532 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
533 "%s: Failed to build valid channel list", __func__);
534 ret = -EINVAL;
535 goto exit;
536 }
537 }
538 }
539#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700540 /*
541 command should be a string having format
542 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
543 */
Amar Singhal0974e402013-02-12 14:27:46 -0800544 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700545 {
Amar Singhal0974e402013-02-12 14:27:46 -0800546 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700547
548 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700549 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700550
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800551 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700552 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800553 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
554 {
555 int suspend = 0;
556 tANI_U8 *ptr = (tANI_U8*)command + 15;
557
558 suspend = *ptr - '0';
559 hdd_set_wlan_suspend_mode(suspend);
560 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800561#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
562 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
563 {
564 tANI_U8 *value = command;
565 int rssi = 0;
566 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
567 eHalStatus status = eHAL_STATUS_SUCCESS;
568
569 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
570 value = value + 15;
571
572 sscanf(value, "%d", &rssi);
573 lookUpThreshold = abs(rssi);
574 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
575 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
576 {
577 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
578 "Neighbor lookup threshold value %d is out of range"
579 " (Min: %d Max: %d)", lookUpThreshold,
580 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
581 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
582 ret = -EINVAL;
583 goto exit;
584 }
585
586 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
587 "%s: Received Command to Set Roam trigger"
588 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
589
590 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
591 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
592 if (eHAL_STATUS_SUCCESS != status)
593 {
594 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
595 "%s: Failed to set roam trigger, try again", __func__);
596 ret = -EPERM;
597 goto exit;
598 }
599
600 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
601 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
602 }
603 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
604 {
605 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
606 int rssi = (-1) * lookUpThreshold;
607 char extra[32];
608 tANI_U8 len = 0;
609
610 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
611 if (copy_to_user(priv_data.buf, &extra, len + 1))
612 {
613 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
614 "%s: failed to copy data to user buffer", __func__);
615 ret = -EFAULT;
616 goto exit;
617 }
618 }
619 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
620 {
621 tANI_U8 *value = command;
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700622 tANI_U16 emptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800623 /* input refresh period is in terms of seconds */
624 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
625 value = value + 18;
626 /* Convert the value from ascii to integer */
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700627 ret = kstrtou16(value, 10, &emptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800628 if (ret < 0)
629 {
630 /* If the input value is greater than max value of datatype, then also
631 kstrtou16 fails */
632 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
633 "%s: kstrtou16 failed ",
634 "Input value may be out of range[%d - %d]",
635 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700636 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
637 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800638 ret = -EINVAL;
639 goto exit;
640 }
641
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700642 emptyScanRefreshPeriod = emptyScanRefreshPeriod * 1000;
643 if ((emptyScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
644 (emptyScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800645 {
646 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700647 "Empty scan refresh period value %d is out of range"
648 " (Min: %d Max: %d)", emptyScanRefreshPeriod/1000,
649 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
650 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800651 ret = -EINVAL;
652 goto exit;
653 }
654
655 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
656 "%s: Received Command to Set roam scan period"
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700657 " (Empty Scan refresh period) = %d", __func__, emptyScanRefreshPeriod/1000);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800658
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700659 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = emptyScanRefreshPeriod;
660 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), emptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800661 }
662 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
663 {
664 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
665 char extra[32];
666 tANI_U8 len = 0;
667
668 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
669 /* Returned value is in units of seconds */
670 if (copy_to_user(priv_data.buf, &extra, len + 1))
671 {
672 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
673 "%s: failed to copy data to user buffer", __func__);
674 ret = -EFAULT;
675 goto exit;
676 }
677 }
678#endif
679#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
680 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
681 {
682 tANI_U8 *value = command;
683 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
684
685 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
686 value = value + 13;
687 /* Convert the value from ascii to integer */
688 ret = kstrtou8(value, 10, &roamRssiDiff);
689 if (ret < 0)
690 {
691 /* If the input value is greater than max value of datatype, then also
692 kstrtou8 fails */
693 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
694 "%s: kstrtou8 failed range [%d - %d]", __func__,
695 CFG_ROAM_RSSI_DIFF_MIN,
696 CFG_ROAM_RSSI_DIFF_MAX);
697 ret = -EINVAL;
698 goto exit;
699 }
700
701 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
702 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
703 {
704 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
705 "Roam rssi diff value %d is out of range"
706 " (Min: %d Max: %d)", roamRssiDiff,
707 CFG_ROAM_RSSI_DIFF_MIN,
708 CFG_ROAM_RSSI_DIFF_MAX);
709 ret = -EINVAL;
710 goto exit;
711 }
712
713 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
714 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
715
716 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
717 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
718 }
719 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
720 {
721 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
722 char extra[32];
723 tANI_U8 len = 0;
724
725 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
726 if (copy_to_user(priv_data.buf, &extra, len + 1))
727 {
728 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
729 "%s: failed to copy data to user buffer", __func__);
730 ret = -EFAULT;
731 goto exit;
732 }
733 }
734#endif
735#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
736 else if (strncmp(command, "GETBAND", 7) == 0)
737 {
738 int band = -1;
739 char extra[32];
740 tANI_U8 len = 0;
741 hdd_getBand_helper(pHddCtx, &band);
742
743 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
744 if (copy_to_user(priv_data.buf, &extra, len + 1))
745 {
746 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
747 "%s: failed to copy data to user buffer", __func__);
748 ret = -EFAULT;
749 goto exit;
750 }
751 }
752 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
753 {
754 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
755 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
756 tANI_U8 revision = 0;
757 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
758 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
759 char extra[32] = {0};
760 tANI_U8 len = 0;
761
762 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
763 {
764 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
765 "%s: failed to get country code", __func__);
766 ret = -EFAULT;
767 goto exit;
768 }
769 pBuf[uBufLen] = '\0';
770 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
771
772 if (0 == strncmp(pBuf, "KR", 2))
773 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
774 else
775 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
776
777 if (copy_to_user(priv_data.buf, &extra, len + 1))
778 {
779 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
780 "%s: failed to copy data to user buffer", __func__);
781 ret = -EFAULT;
782 goto exit;
783 }
784 }
785 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
786 {
787 tANI_U8 *value = command;
788 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
789 tANI_U8 numChannels = 0;
790 eHalStatus status = eHAL_STATUS_SUCCESS;
791
792 status = hdd_parse_channellist(value, ChannelList, &numChannels);
793 if (eHAL_STATUS_SUCCESS != status)
794 {
795 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
796 "%s: Failed to parse channel list information", __func__);
797 ret = -EINVAL;
798 goto exit;
799 }
800
801 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
802 {
803 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
804 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
805 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
806 ret = -EINVAL;
807 goto exit;
808 }
809 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
810 numChannels);
811 if (eHAL_STATUS_SUCCESS != status)
812 {
813 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
814 "%s: Failed to update channel list information", __func__);
815 ret = -EINVAL;
816 goto exit;
817 }
818 }
819 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
820 {
821 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
822 tANI_U8 numChannels = 0;
823 tANI_U8 len = 0, j = 0;
824 char extra[128] = {0};
825
826 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
827 ChannelList, &numChannels ))
828 {
829 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
830 "%s: failed to get roam scan channel list", __func__);
831 ret = -EFAULT;
832 goto exit;
833 }
834 /* output channel list is of the format
835 [Number of roam scan channels][Channel1][Channel2]... */
836 /* copy the number of channels in the 0th index */
837 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
838 for (j = 0; (j < numChannels); j++)
839 {
840 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
841 }
842
843 if (copy_to_user(priv_data.buf, &extra, len + 1))
844 {
845 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
846 "%s: failed to copy data to user buffer", __func__);
847 ret = -EFAULT;
848 goto exit;
849 }
850 }
851#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700852 else {
853 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
854 __func__, command);
855 }
856
Jeff Johnson295189b2012-06-20 16:38:30 -0700857 }
858exit:
859 if (command)
860 {
861 kfree(command);
862 }
863 return ret;
864}
865
Srinivas Girigowdade697412013-02-14 16:31:48 -0800866#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
867void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
868{
869 eCsrBand band = -1;
870 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
871 switch (band)
872 {
873 case eCSR_BAND_ALL:
874 *pBand = WLAN_HDD_UI_BAND_AUTO;
875 break;
876
877 case eCSR_BAND_24:
878 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
879 break;
880
881 case eCSR_BAND_5G:
882 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
883 break;
884
885 default:
886 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
887 *pBand = -1;
888 break;
889 }
890}
891
892/**---------------------------------------------------------------------------
893
894 \brief hdd_parse_countryrev() - HDD Parse country code revision
895
896 This function parses the country code revision passed in the format
897 SETCOUNTRYREV<space><Country code><space>revision
898
899 \param - pValue Pointer to input country code revision
900 \param - pCountryCode Pointer to local output array to record country code
901 \param - pRevision Pointer to store revision integer number
902
903 \return - 0 for success non-zero for failure
904
905 --------------------------------------------------------------------------*/
906VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
907{
908 tANI_U8 *inPtr = pValue;
909 int tempInt;
910
911 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
912 /*no argument after the command*/
913 if (NULL == inPtr)
914 {
915 return -EINVAL;
916 }
917
918 /*no space after the command*/
919 else if (SPACE_ASCII_VALUE != *inPtr)
920 {
921 return -EINVAL;
922 }
923
924 /*removing empty spaces*/
925 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
926
927 /*no argument followed by spaces*/
928 if ('\0' == *inPtr)
929 {
930 return -EINVAL;
931 }
932
933 /*getting the first argument ie the country code */
934 sscanf(inPtr, "%s ", pCountryCode);
935
936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
937 "Country code is : %s", pCountryCode);
938
939 /*inPtr pointing to the beginning of first space after country code */
940 inPtr = strpbrk( inPtr, " " );
941 /*no revision number after the country code argument */
942 if (NULL == inPtr)
943 {
944 return -EINVAL;
945 }
946
947 inPtr++;
948
949 /*removing empty space*/
950 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
951
952 /*no channel list after the number of channels argument and spaces*/
953 if (0 == strncmp(pCountryCode, "KR", 2))
954 {
955 if ('\0' == *inPtr)
956 {
957 return -EINVAL;
958 }
959
960 sscanf(inPtr, "%d", &tempInt);
961 *pRevision = tempInt;
962 }
963 else
964 {
965 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
966 "Revision input is required only for Country KR");
967 return -EINVAL;
968 }
969 return VOS_STATUS_SUCCESS;
970}
971
972/**---------------------------------------------------------------------------
973
974 \brief hdd_parse_channellist() - HDD Parse channel list
975
976 This function parses the channel list passed in the format
977 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -0700978 if the Number of channels (N) does not match with the actual number of channels passed
979 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
980 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
981 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
982 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -0800983
984 \param - pValue Pointer to input channel list
985 \param - ChannelList Pointer to local output array to record channel list
986 \param - pNumChannels Pointer to number of roam scan channels
987
988 \return - 0 for success non-zero for failure
989
990 --------------------------------------------------------------------------*/
991VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
992{
993 tANI_U8 *inPtr = pValue;
994 int tempInt;
995 int j = 0;
996 int v = 0;
997 char buf[32];
998
999 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1000 /*no argument after the command*/
1001 if (NULL == inPtr)
1002 {
1003 return -EINVAL;
1004 }
1005
1006 /*no space after the command*/
1007 else if (SPACE_ASCII_VALUE != *inPtr)
1008 {
1009 return -EINVAL;
1010 }
1011
1012 /*removing empty spaces*/
1013 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
1014
1015 /*no argument followed by spaces*/
1016 if ('\0' == *inPtr)
1017 {
1018 return -EINVAL;
1019 }
1020
1021 /*getting the first argument ie the number of channels*/
1022 sscanf(inPtr, "%s ", buf);
1023 v = kstrtos32(buf, 10, &tempInt);
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001024 if ((v < 0) || (tempInt <= 0)) return -EINVAL;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001025
1026 *pNumChannels = tempInt;
1027
1028 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1029 "Number of channels are: %d", *pNumChannels);
1030
1031 for (j = 0; j < (*pNumChannels); j++)
1032 {
1033 /*inPtr pointing to the beginning of first space after number of channels*/
1034 inPtr = strpbrk( inPtr, " " );
1035 /*no channel list after the number of channels argument*/
1036 if (NULL == inPtr)
1037 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001038 if (0 != j)
1039 {
1040 *pNumChannels = j;
1041 return VOS_STATUS_SUCCESS;
1042 }
1043 else
1044 {
1045 return -EINVAL;
1046 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001047 }
1048
1049 /*removing empty space*/
1050 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1051
1052 /*no channel list after the number of channels argument and spaces*/
1053 if ( '\0' == *inPtr )
1054 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001055 if (0 != j)
1056 {
1057 *pNumChannels = j;
1058 return VOS_STATUS_SUCCESS;
1059 }
1060 else
1061 {
1062 return -EINVAL;
1063 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001064 }
1065
1066 sscanf(inPtr, "%s ", buf);
1067 v = kstrtos32(buf, 10, &tempInt);
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001068 if ((v < 0) || (tempInt <= 0)) return -EINVAL;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001069 pChannelList[j] = tempInt;
1070
1071 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1072 "Channel %d added to preferred channel list",
1073 pChannelList[j] );
1074 }
1075
Srinivas Girigowdade697412013-02-14 16:31:48 -08001076 return VOS_STATUS_SUCCESS;
1077}
1078
1079#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001080/**---------------------------------------------------------------------------
1081
1082 \brief hdd_open() - HDD Open function
1083
1084 This is called in response to ifconfig up
1085
1086 \param - dev Pointer to net_device structure
1087
1088 \return - 0 for success non-zero for failure
1089
1090 --------------------------------------------------------------------------*/
1091int hdd_open (struct net_device *dev)
1092{
1093 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1094 hdd_context_t *pHddCtx;
1095 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1096 VOS_STATUS status;
1097 v_BOOL_t in_standby = TRUE;
1098
1099 if (NULL == pAdapter)
1100 {
1101 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001102 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001103 return -ENODEV;
1104 }
1105
1106 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1107 if (NULL == pHddCtx)
1108 {
1109 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001110 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001111 return -ENODEV;
1112 }
1113
1114 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1115 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1116 {
1117 if( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
1118 {
1119 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of "
1120 "standby", __func__, pAdapter->device_mode);
1121 in_standby = FALSE;
1122 break;
1123 }
1124 else
1125 {
1126 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1127 pAdapterNode = pNext;
1128 }
1129 }
1130
1131 if (TRUE == in_standby)
1132 {
1133 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
1134 {
1135 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
1136 "wlan out of power save", __func__);
1137 return -EINVAL;
1138 }
1139 }
1140
1141 pAdapter->event_flags |= DEVICE_IFACE_OPENED;
1142 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
1143 {
1144 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001145 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001146 /* Enable TX queues only when we are connected */
1147 netif_tx_start_all_queues(dev);
1148 }
1149
1150 return 0;
1151}
1152
1153int hdd_mon_open (struct net_device *dev)
1154{
1155 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1156
1157 if(pAdapter == NULL) {
1158 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001159 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001160 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001161 }
1162
1163 netif_start_queue(dev);
1164
1165 return 0;
1166}
1167/**---------------------------------------------------------------------------
1168
1169 \brief hdd_stop() - HDD stop function
1170
1171 This is called in response to ifconfig down
1172
1173 \param - dev Pointer to net_device structure
1174
1175 \return - 0 for success non-zero for failure
1176
1177 --------------------------------------------------------------------------*/
1178
1179int hdd_stop (struct net_device *dev)
1180{
1181 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1182 hdd_context_t *pHddCtx;
1183 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1184 VOS_STATUS status;
1185 v_BOOL_t enter_standby = TRUE;
1186
1187 ENTER();
1188
1189 if (NULL == pAdapter)
1190 {
1191 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001192 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001193 return -ENODEV;
1194 }
1195
1196 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1197 if (NULL == pHddCtx)
1198 {
1199 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001200 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001201 return -ENODEV;
1202 }
1203
1204 pAdapter->event_flags &= ~(DEVICE_IFACE_OPENED);
1205 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
1206 netif_tx_disable(pAdapter->dev);
1207 netif_carrier_off(pAdapter->dev);
1208
1209
1210 /* SoftAP ifaces should never go in power save mode
1211 making sure same here. */
1212 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
1213 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001214 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001215 )
1216 {
1217 /* SoftAP mode, so return from here */
1218 EXIT();
1219 return 0;
1220 }
1221
1222 /* Find if any iface is up then
1223 if any iface is up then can't put device to sleep/ power save mode. */
1224 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1225 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1226 {
1227 if ( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
1228 {
1229 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
1230 "put device to sleep", __func__, pAdapter->device_mode);
1231 enter_standby = FALSE;
1232 break;
1233 }
1234 else
1235 {
1236 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1237 pAdapterNode = pNext;
1238 }
1239 }
1240
1241 if (TRUE == enter_standby)
1242 {
1243 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
1244 "entering standby", __func__);
1245 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
1246 {
1247 /*log and return success*/
1248 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
1249 "wlan in power save", __func__);
1250 }
1251 }
1252
1253 EXIT();
1254 return 0;
1255}
1256
1257/**---------------------------------------------------------------------------
1258
1259 \brief hdd_uninit() - HDD uninit function
1260
1261 This is called during the netdev unregister to uninitialize all data
1262associated with the device
1263
1264 \param - dev Pointer to net_device structure
1265
1266 \return - void
1267
1268 --------------------------------------------------------------------------*/
1269static void hdd_uninit (struct net_device *dev)
1270{
1271 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1272
1273 ENTER();
1274
1275 do
1276 {
1277 if (NULL == pAdapter)
1278 {
1279 hddLog(VOS_TRACE_LEVEL_FATAL,
1280 "%s: NULL pAdapter", __func__);
1281 break;
1282 }
1283
1284 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1285 {
1286 hddLog(VOS_TRACE_LEVEL_FATAL,
1287 "%s: Invalid magic", __func__);
1288 break;
1289 }
1290
1291 if (NULL == pAdapter->pHddCtx)
1292 {
1293 hddLog(VOS_TRACE_LEVEL_FATAL,
1294 "%s: NULL pHddCtx", __func__);
1295 break;
1296 }
1297
1298 if (dev != pAdapter->dev)
1299 {
1300 hddLog(VOS_TRACE_LEVEL_FATAL,
1301 "%s: Invalid device reference", __func__);
1302 /* we haven't validated all cases so let this go for now */
1303 }
1304
1305 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
1306
1307 /* after uninit our adapter structure will no longer be valid */
1308 pAdapter->dev = NULL;
1309 pAdapter->magic = 0;
1310 } while (0);
1311
1312 EXIT();
1313}
1314
1315/**---------------------------------------------------------------------------
1316
1317 \brief hdd_release_firmware() -
1318
1319 This function calls the release firmware API to free the firmware buffer.
1320
1321 \param - pFileName Pointer to the File Name.
1322 pCtx - Pointer to the adapter .
1323
1324
1325 \return - 0 for success, non zero for failure
1326
1327 --------------------------------------------------------------------------*/
1328
1329VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
1330{
1331 VOS_STATUS status = VOS_STATUS_SUCCESS;
1332 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1333 ENTER();
1334
1335
1336 if (!strcmp(WLAN_FW_FILE, pFileName)) {
1337
1338 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
1339
1340 if(pHddCtx->fw) {
1341 release_firmware(pHddCtx->fw);
1342 pHddCtx->fw = NULL;
1343 }
1344 else
1345 status = VOS_STATUS_E_FAILURE;
1346 }
1347 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
1348 if(pHddCtx->nv) {
1349 release_firmware(pHddCtx->nv);
1350 pHddCtx->nv = NULL;
1351 }
1352 else
1353 status = VOS_STATUS_E_FAILURE;
1354
1355 }
1356
1357 EXIT();
1358 return status;
1359}
1360
1361/**---------------------------------------------------------------------------
1362
1363 \brief hdd_request_firmware() -
1364
1365 This function reads the firmware file using the request firmware
1366 API and returns the the firmware data and the firmware file size.
1367
1368 \param - pfileName - Pointer to the file name.
1369 - pCtx - Pointer to the adapter .
1370 - ppfw_data - Pointer to the pointer of the firmware data.
1371 - pSize - Pointer to the file size.
1372
1373 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
1374
1375 --------------------------------------------------------------------------*/
1376
1377
1378VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
1379{
1380 int status;
1381 VOS_STATUS retval = VOS_STATUS_SUCCESS;
1382 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1383 ENTER();
1384
1385 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
1386
1387 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
1388
1389 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1390 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
1391 __func__, pfileName);
1392 retval = VOS_STATUS_E_FAILURE;
1393 }
1394
1395 else {
1396 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
1397 *pSize = pHddCtx->fw->size;
1398 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
1399 __func__, *pSize);
1400 }
1401 }
1402 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
1403
1404 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
1405
1406 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
1407 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
1408 __func__, pfileName);
1409 retval = VOS_STATUS_E_FAILURE;
1410 }
1411
1412 else {
1413 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
1414 *pSize = pHddCtx->nv->size;
1415 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
1416 __func__, *pSize);
1417 }
1418 }
1419
1420 EXIT();
1421 return retval;
1422}
1423/**---------------------------------------------------------------------------
1424 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
1425
1426 This is the function invoked by SME to inform the result of a full power
1427 request issued by HDD
1428
1429 \param - callbackcontext - Pointer to cookie
1430 status - result of request
1431
1432 \return - None
1433
1434--------------------------------------------------------------------------*/
1435void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
1436{
1437 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
1438
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001439 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001440 if(&pHddCtx->full_pwr_comp_var)
1441 {
1442 complete(&pHddCtx->full_pwr_comp_var);
1443 }
1444}
1445
1446/**---------------------------------------------------------------------------
1447
1448 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
1449
1450 This is the function invoked by SME to inform the result of BMPS
1451 request issued by HDD
1452
1453 \param - callbackcontext - Pointer to cookie
1454 status - result of request
1455
1456 \return - None
1457
1458--------------------------------------------------------------------------*/
1459void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
1460{
1461
1462 struct completion *completion_var = (struct completion*) callbackContext;
1463
1464 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
1465 if(completion_var != NULL)
1466 {
1467 complete(completion_var);
1468 }
1469}
1470
1471/**---------------------------------------------------------------------------
1472
1473 \brief hdd_get_cfg_file_size() -
1474
1475 This function reads the configuration file using the request firmware
1476 API and returns the configuration file size.
1477
1478 \param - pCtx - Pointer to the adapter .
1479 - pFileName - Pointer to the file name.
1480 - pBufSize - Pointer to the buffer size.
1481
1482 \return - 0 for success, non zero for failure
1483
1484 --------------------------------------------------------------------------*/
1485
1486VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
1487{
1488 int status;
1489 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1490
1491 ENTER();
1492
1493 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
1494
1495 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1496 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
1497 status = VOS_STATUS_E_FAILURE;
1498 }
1499 else {
1500 *pBufSize = pHddCtx->fw->size;
1501 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
1502 release_firmware(pHddCtx->fw);
1503 pHddCtx->fw = NULL;
1504 }
1505
1506 EXIT();
1507 return VOS_STATUS_SUCCESS;
1508}
1509
1510/**---------------------------------------------------------------------------
1511
1512 \brief hdd_read_cfg_file() -
1513
1514 This function reads the configuration file using the request firmware
1515 API and returns the cfg data and the buffer size of the configuration file.
1516
1517 \param - pCtx - Pointer to the adapter .
1518 - pFileName - Pointer to the file name.
1519 - pBuffer - Pointer to the data buffer.
1520 - pBufSize - Pointer to the buffer size.
1521
1522 \return - 0 for success, non zero for failure
1523
1524 --------------------------------------------------------------------------*/
1525
1526VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
1527 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
1528{
1529 int status;
1530 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1531
1532 ENTER();
1533
1534 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
1535
1536 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1537 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
1538 return VOS_STATUS_E_FAILURE;
1539 }
1540 else {
1541 if(*pBufSize != pHddCtx->fw->size) {
1542 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
1543 "file size", __func__);
1544 release_firmware(pHddCtx->fw);
1545 pHddCtx->fw = NULL;
1546 return VOS_STATUS_E_FAILURE;
1547 }
1548 else {
1549 if(pBuffer) {
1550 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
1551 }
1552 release_firmware(pHddCtx->fw);
1553 pHddCtx->fw = NULL;
1554 }
1555 }
1556
1557 EXIT();
1558
1559 return VOS_STATUS_SUCCESS;
1560}
1561
1562/**---------------------------------------------------------------------------
1563
Jeff Johnson295189b2012-06-20 16:38:30 -07001564 \brief hdd_set_mac_address() -
1565
1566 This function sets the user specified mac address using
1567 the command ifconfig wlanX hw ether <mac adress>.
1568
1569 \param - dev - Pointer to the net device.
1570 - addr - Pointer to the sockaddr.
1571 \return - 0 for success, non zero for failure
1572
1573 --------------------------------------------------------------------------*/
1574
1575static int hdd_set_mac_address(struct net_device *dev, void *addr)
1576{
1577 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1578 struct sockaddr *psta_mac_addr = addr;
1579 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1580
1581 ENTER();
1582
1583 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
1584
1585#ifdef HDD_SESSIONIZE
1586 // set the MAC address though the STA ID CFG.
1587 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
1588 (v_U8_t *)&pAdapter->macAddressCurrent,
1589 sizeof( pAdapter->macAddressCurrent ),
1590 hdd_set_mac_addr_cb, VOS_FALSE );
1591#endif
1592
1593 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
1594
1595 EXIT();
1596 return halStatus;
1597}
1598
1599tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
1600{
1601 int i;
1602 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
1603 {
1604 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
1605 break;
1606 }
1607
1608 if( VOS_MAX_CONCURRENCY_PERSONA == i)
1609 return NULL;
1610
1611 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
1612 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
1613}
1614
1615void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
1616{
1617 int i;
1618 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
1619 {
1620 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
1621 {
1622 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
1623 break;
1624 }
1625 }
1626 return;
1627}
1628
1629#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1630 static struct net_device_ops wlan_drv_ops = {
1631 .ndo_open = hdd_open,
1632 .ndo_stop = hdd_stop,
1633 .ndo_uninit = hdd_uninit,
1634 .ndo_start_xmit = hdd_hard_start_xmit,
1635 .ndo_tx_timeout = hdd_tx_timeout,
1636 .ndo_get_stats = hdd_stats,
1637 .ndo_do_ioctl = hdd_ioctl,
1638 .ndo_set_mac_address = hdd_set_mac_address,
1639 .ndo_select_queue = hdd_select_queue,
1640#ifdef WLAN_FEATURE_PACKET_FILTERING
1641#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
1642 .ndo_set_rx_mode = hdd_set_multicast_list,
1643#else
1644 .ndo_set_multicast_list = hdd_set_multicast_list,
1645#endif //LINUX_VERSION_CODE
1646#endif
1647 };
Jeff Johnson295189b2012-06-20 16:38:30 -07001648 static struct net_device_ops wlan_mon_drv_ops = {
1649 .ndo_open = hdd_mon_open,
1650 .ndo_stop = hdd_stop,
1651 .ndo_uninit = hdd_uninit,
1652 .ndo_start_xmit = hdd_mon_hard_start_xmit,
1653 .ndo_tx_timeout = hdd_tx_timeout,
1654 .ndo_get_stats = hdd_stats,
1655 .ndo_do_ioctl = hdd_ioctl,
1656 .ndo_set_mac_address = hdd_set_mac_address,
1657 };
Jeff Johnson295189b2012-06-20 16:38:30 -07001658
1659#endif
1660
1661void hdd_set_station_ops( struct net_device *pWlanDev )
1662{
1663#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1664 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
1665 pWlanDev->netdev_ops = &wlan_drv_ops;
1666#else
1667 pWlanDev->open = hdd_open;
1668 pWlanDev->stop = hdd_stop;
1669 pWlanDev->uninit = hdd_uninit;
1670 pWlanDev->hard_start_xmit = NULL;
1671 pWlanDev->tx_timeout = hdd_tx_timeout;
1672 pWlanDev->get_stats = hdd_stats;
1673 pWlanDev->do_ioctl = hdd_ioctl;
1674 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
1675 pWlanDev->set_mac_address = hdd_set_mac_address;
1676#endif
1677}
1678
Jeff Johnsoneed415b2013-01-18 16:11:20 -08001679static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07001680{
1681 struct net_device *pWlanDev = NULL;
1682 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001683 /*
1684 * cfg80211 initialization and registration....
1685 */
1686 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
1687
Jeff Johnson295189b2012-06-20 16:38:30 -07001688 if(pWlanDev != NULL)
1689 {
1690
1691 //Save the pointer to the net_device in the HDD adapter
1692 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
1693
Jeff Johnson295189b2012-06-20 16:38:30 -07001694 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
1695
1696 pAdapter->dev = pWlanDev;
1697 pAdapter->pHddCtx = pHddCtx;
1698 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
1699
1700 init_completion(&pAdapter->session_open_comp_var);
1701 init_completion(&pAdapter->session_close_comp_var);
1702 init_completion(&pAdapter->disconnect_comp_var);
1703 init_completion(&pAdapter->linkup_event_var);
1704 init_completion(&pAdapter->cancel_rem_on_chan_var);
1705 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001706#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1707 init_completion(&pAdapter->offchannel_tx_event);
1708#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001709 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08001710#ifdef FEATURE_WLAN_TDLS
1711 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001712 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08001713#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001714 init_completion(&pHddCtx->mc_sus_event_var);
1715 init_completion(&pHddCtx->tx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07001716 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07001717
Jeff Johnson295189b2012-06-20 16:38:30 -07001718 pAdapter->isLinkUpSvcNeeded = FALSE;
1719 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
1720 //Init the net_device structure
1721 strlcpy(pWlanDev->name, name, IFNAMSIZ);
1722
1723 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
1724 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
1725 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
1726 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
1727
1728 hdd_set_station_ops( pAdapter->dev );
1729
1730 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07001731 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
1732 pAdapter->wdev.wiphy = pHddCtx->wiphy;
1733 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07001734 /* set pWlanDev's parent to underlying device */
1735 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
1736 }
1737
1738 return pAdapter;
1739}
1740
1741VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
1742{
1743 struct net_device *pWlanDev = pAdapter->dev;
1744 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1745 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1746 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1747
1748 if( rtnl_lock_held )
1749 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001750 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07001751 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
1752 {
1753 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
1754 return VOS_STATUS_E_FAILURE;
1755 }
1756 }
1757 if (register_netdevice(pWlanDev))
1758 {
1759 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
1760 return VOS_STATUS_E_FAILURE;
1761 }
1762 }
1763 else
1764 {
1765 if(register_netdev(pWlanDev))
1766 {
1767 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
1768 return VOS_STATUS_E_FAILURE;
1769 }
1770 }
1771 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
1772
1773 return VOS_STATUS_SUCCESS;
1774}
1775
1776eHalStatus hdd_smeCloseSessionCallback(void *pContext)
1777{
1778 if(pContext != NULL)
1779 {
1780 clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags);
1781
1782 /* need to make sure all of our scheduled work has completed.
1783 * This callback is called from MC thread context, so it is safe to
1784 * to call below flush workqueue API from here.
1785 */
1786 flush_scheduled_work();
1787 complete(&((hdd_adapter_t*)pContext)->session_close_comp_var);
1788 }
1789 return eHAL_STATUS_SUCCESS;
1790}
1791
1792VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
1793{
1794 struct net_device *pWlanDev = pAdapter->dev;
1795 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1796 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1797 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1798 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1799 int rc = 0;
1800
1801 INIT_COMPLETION(pAdapter->session_open_comp_var);
1802 //Open a SME session for future operation
1803 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
1804 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
1805 if ( !HAL_STATUS_SUCCESS( halStatus ) )
1806 {
1807 hddLog(VOS_TRACE_LEVEL_FATAL,
1808 "sme_OpenSession() failed with status code %08d [x%08lx]",
1809 halStatus, halStatus );
1810 status = VOS_STATUS_E_FAILURE;
1811 goto error_sme_open;
1812 }
1813
1814 //Block on a completion variable. Can't wait forever though.
1815 rc = wait_for_completion_interruptible_timeout(
1816 &pAdapter->session_open_comp_var,
1817 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1818 if (!rc)
1819 {
1820 hddLog(VOS_TRACE_LEVEL_FATAL,
1821 "Session is not opened within timeout period code %08d", rc );
1822 status = VOS_STATUS_E_FAILURE;
1823 goto error_sme_open;
1824 }
1825
1826 // Register wireless extensions
1827 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
1828 {
1829 hddLog(VOS_TRACE_LEVEL_FATAL,
1830 "hdd_register_wext() failed with status code %08d [x%08lx]",
1831 halStatus, halStatus );
1832 status = VOS_STATUS_E_FAILURE;
1833 goto error_register_wext;
1834 }
1835 //Safe to register the hard_start_xmit function again
1836#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1837 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
1838#else
1839 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
1840#endif
1841
1842 //Set the Connection State to Not Connected
1843 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
1844
1845 //Set the default operation channel
1846 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
1847
1848 /* Make the default Auth Type as OPEN*/
1849 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
1850
1851 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
1852 {
1853 hddLog(VOS_TRACE_LEVEL_FATAL,
1854 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
1855 status, status );
1856 goto error_init_txrx;
1857 }
1858
1859 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1860
1861 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
1862 {
1863 hddLog(VOS_TRACE_LEVEL_FATAL,
1864 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
1865 status, status );
1866 goto error_wmm_init;
1867 }
1868
1869 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1870
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001871#ifdef FEATURE_WLAN_TDLS
1872 if(0 != wlan_hdd_tdls_init(pAdapter))
1873 {
1874 status = VOS_STATUS_E_FAILURE;
1875 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
1876 goto error_tdls_init;
1877 }
1878 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
1879#endif
1880
Jeff Johnson295189b2012-06-20 16:38:30 -07001881 return VOS_STATUS_SUCCESS;
1882
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001883#ifdef FEATURE_WLAN_TDLS
1884error_tdls_init:
1885 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1886 hdd_wmm_adapter_close(pAdapter);
1887#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001888error_wmm_init:
1889 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1890 hdd_deinit_tx_rx(pAdapter);
1891error_init_txrx:
1892 hdd_UnregisterWext(pWlanDev);
1893error_register_wext:
1894 if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
1895 {
1896 INIT_COMPLETION(pAdapter->session_close_comp_var);
1897 if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
1898 pAdapter->sessionId,
1899 hdd_smeCloseSessionCallback, pAdapter ) )
1900 {
1901 //Block on a completion variable. Can't wait forever though.
1902 wait_for_completion_interruptible_timeout(
1903 &pAdapter->session_close_comp_var,
1904 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1905 }
1906}
1907error_sme_open:
1908 return status;
1909}
1910
Jeff Johnson295189b2012-06-20 16:38:30 -07001911void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1912{
1913 hdd_cfg80211_state_t *cfgState;
1914
1915 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1916
1917 if( NULL != cfgState->buf )
1918 {
1919 int rc;
1920 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
1921 rc = wait_for_completion_interruptible_timeout(
1922 &pAdapter->tx_action_cnf_event,
1923 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
1924 if(!rc)
1925 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08001926 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001927 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
1928 }
1929 }
1930 return;
1931}
Jeff Johnson295189b2012-06-20 16:38:30 -07001932
1933void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1934{
1935 ENTER();
1936 switch ( pAdapter->device_mode )
1937 {
1938 case WLAN_HDD_INFRA_STATION:
1939 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07001940 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07001941 {
1942 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1943 {
1944 hdd_deinit_tx_rx( pAdapter );
1945 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1946 }
1947
1948 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
1949 {
1950 hdd_wmm_adapter_close( pAdapter );
1951 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1952 }
1953
Jeff Johnson295189b2012-06-20 16:38:30 -07001954 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001955#ifdef FEATURE_WLAN_TDLS
1956 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
1957 {
1958 wlan_hdd_tdls_exit(pAdapter);
1959 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
1960 }
1961#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001962
1963 break;
1964 }
1965
1966 case WLAN_HDD_SOFTAP:
1967 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07001968 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001969 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001970
1971 hdd_unregister_hostapd(pAdapter);
1972 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07001973 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07001974 break;
1975 }
1976
1977 case WLAN_HDD_MONITOR:
1978 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001979 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07001980 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1981 {
1982 hdd_deinit_tx_rx( pAdapter );
1983 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1984 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001985 if(NULL != pAdapterforTx)
1986 {
1987 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
1988 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001989 break;
1990 }
1991
1992
1993 default:
1994 break;
1995 }
1996
1997 EXIT();
1998}
1999
2000void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
2001{
2002 struct net_device *pWlanDev = pAdapter->dev;
2003
2004 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
2005 if( rtnl_held )
2006 {
2007 unregister_netdevice(pWlanDev);
2008 }
2009 else
2010 {
2011 unregister_netdev(pWlanDev);
2012 }
2013 // note that the pAdapter is no longer valid at this point
2014 // since the memory has been reclaimed
2015 }
2016
2017}
2018
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08002019void hdd_set_pwrparams(hdd_context_t *pHddCtx)
2020{
2021 tSirSetPowerParamsReq powerRequest = { 0 };
2022
2023 powerRequest.uIgnoreDTIM = 1;
2024
2025 if (pHddCtx->cfg_ini->enableModulatedDTIM)
2026 {
2027 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
2028 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2029 }
2030 else
2031 {
2032 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
2033 }
2034
2035 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
2036 *specified during Enter/Exit BMPS when LCD off*/
2037 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2038 NULL, eANI_BOOLEAN_FALSE);
2039 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2040 NULL, eANI_BOOLEAN_FALSE);
2041
2042 /* switch to the DTIM specified in cfg.ini */
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
2049void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
2050{
2051 /*Switch back to DTIM 1*/
2052 tSirSetPowerParamsReq powerRequest = { 0 };
2053
2054 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
2055 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2056
2057 /* Update ignoreDTIM and ListedInterval in CFG with default values */
2058 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2059 NULL, eANI_BOOLEAN_FALSE);
2060 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2061 NULL, eANI_BOOLEAN_FALSE);
2062
2063 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2064 "Switch to DTIM%d",powerRequest.uListenInterval);
2065 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2066
2067}
2068
Jeff Johnson295189b2012-06-20 16:38:30 -07002069VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
2070{
2071 VOS_STATUS status = VOS_STATUS_SUCCESS;
2072
2073 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2074 {
2075 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2076 }
2077
2078 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2079 {
2080 sme_StartAutoBmpsTimer(pHddCtx->hHal);
2081 }
2082
2083 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2084 {
2085 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2086 }
2087
2088 return status;
2089}
2090
2091VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
2092{
2093 hdd_adapter_t *pAdapter = NULL;
2094 eHalStatus halStatus;
2095 VOS_STATUS status = VOS_STATUS_E_INVAL;
2096 v_BOOL_t disableBmps = FALSE;
2097 v_BOOL_t disableImps = FALSE;
2098
2099 switch(session_type)
2100 {
2101 case WLAN_HDD_INFRA_STATION:
2102 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002103 case WLAN_HDD_P2P_CLIENT:
2104 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002105 //Exit BMPS -> Is Sta/P2P Client is already connected
2106 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
2107 if((NULL != pAdapter)&&
2108 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2109 {
2110 disableBmps = TRUE;
2111 }
2112
2113 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
2114 if((NULL != pAdapter)&&
2115 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2116 {
2117 disableBmps = TRUE;
2118 }
2119
2120 //Exit both Bmps and Imps incase of Go/SAP Mode
2121 if((WLAN_HDD_SOFTAP == session_type) ||
2122 (WLAN_HDD_P2P_GO == session_type))
2123 {
2124 disableBmps = TRUE;
2125 disableImps = TRUE;
2126 }
2127
2128 if(TRUE == disableImps)
2129 {
2130 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2131 {
2132 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2133 }
2134 }
2135
2136 if(TRUE == disableBmps)
2137 {
2138 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2139 {
2140 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2141
2142 if(eHAL_STATUS_SUCCESS != halStatus)
2143 {
2144 status = VOS_STATUS_E_FAILURE;
2145 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
2146 VOS_ASSERT(0);
2147 return status;
2148 }
2149 }
2150
2151 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2152 {
2153 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
2154
2155 if(eHAL_STATUS_SUCCESS != halStatus)
2156 {
2157 status = VOS_STATUS_E_FAILURE;
2158 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
2159 VOS_ASSERT(0);
2160 return status;
2161 }
2162 }
2163 }
2164
2165 if((TRUE == disableBmps) ||
2166 (TRUE == disableImps))
2167 {
2168 /* Now, get the chip into Full Power now */
2169 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
2170 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
2171 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
2172
2173 if(halStatus != eHAL_STATUS_SUCCESS)
2174 {
2175 if(halStatus == eHAL_STATUS_PMC_PENDING)
2176 {
2177 //Block on a completion variable. Can't wait forever though
2178 wait_for_completion_interruptible_timeout(
2179 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
2180 }
2181 else
2182 {
2183 status = VOS_STATUS_E_FAILURE;
2184 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
2185 VOS_ASSERT(0);
2186 return status;
2187 }
2188 }
2189
2190 status = VOS_STATUS_SUCCESS;
2191 }
2192
2193 break;
2194 }
2195 return status;
2196}
2197
2198hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002199 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07002200 tANI_U8 rtnl_held )
2201{
2202 hdd_adapter_t *pAdapter = NULL;
2203 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
2204 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2205 VOS_STATUS exitbmpsStatus;
2206
2207 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
2208
2209 //Disable BMPS incase of Concurrency
2210 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
2211
2212 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
2213 {
2214 //Fail to Exit BMPS
2215 VOS_ASSERT(0);
2216 return NULL;
2217 }
2218
2219 switch(session_type)
2220 {
2221 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002222 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002223 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002224 {
2225 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2226
2227 if( NULL == pAdapter )
2228 return NULL;
2229
Jeff Johnsone7245742012-09-05 17:12:55 -07002230 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
2231 NL80211_IFTYPE_P2P_CLIENT:
2232 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07002233
Jeff Johnson295189b2012-06-20 16:38:30 -07002234 pAdapter->device_mode = session_type;
2235
2236 status = hdd_init_station_mode( pAdapter );
2237 if( VOS_STATUS_SUCCESS != status )
2238 goto err_free_netdev;
2239
2240 status = hdd_register_interface( pAdapter, rtnl_held );
2241 if( VOS_STATUS_SUCCESS != status )
2242 {
2243 hdd_deinit_adapter(pHddCtx, pAdapter);
2244 goto err_free_netdev;
2245 }
2246 //Stop the Interface TX queue.
2247 netif_tx_disable(pAdapter->dev);
2248 //netif_tx_disable(pWlanDev);
2249 netif_carrier_off(pAdapter->dev);
2250
2251 break;
2252 }
2253
Jeff Johnson295189b2012-06-20 16:38:30 -07002254 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002255 case WLAN_HDD_SOFTAP:
2256 {
2257 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
2258 if( NULL == pAdapter )
2259 return NULL;
2260
Jeff Johnson295189b2012-06-20 16:38:30 -07002261 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
2262 NL80211_IFTYPE_AP:
2263 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002264 pAdapter->device_mode = session_type;
2265
2266 status = hdd_init_ap_mode(pAdapter);
2267 if( VOS_STATUS_SUCCESS != status )
2268 goto err_free_netdev;
2269
2270 status = hdd_register_hostapd( pAdapter, rtnl_held );
2271 if( VOS_STATUS_SUCCESS != status )
2272 {
2273 hdd_deinit_adapter(pHddCtx, pAdapter);
2274 goto err_free_netdev;
2275 }
2276
2277 netif_tx_disable(pAdapter->dev);
2278 netif_carrier_off(pAdapter->dev);
2279
2280 hdd_set_conparam( 1 );
2281 break;
2282 }
2283 case WLAN_HDD_MONITOR:
2284 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002285 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2286 if( NULL == pAdapter )
2287 return NULL;
2288
2289 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
2290 pAdapter->device_mode = session_type;
2291 status = hdd_register_interface( pAdapter, rtnl_held );
2292#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
2293 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
2294#else
2295 pAdapter->dev->open = hdd_mon_open;
2296 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
2297#endif
2298 hdd_init_tx_rx( pAdapter );
2299 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2300 //Set adapter to be used for data tx. It will use either GO or softap.
2301 pAdapter->sessionCtx.monitor.pAdapterForTx =
2302 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07002303 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
2304 {
2305 pAdapter->sessionCtx.monitor.pAdapterForTx =
2306 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
2307 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002308 /* This workqueue will be used to transmit management packet over
2309 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07002310 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
2311 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
2312 return NULL;
2313 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07002314
Jeff Johnson295189b2012-06-20 16:38:30 -07002315 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
2316 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07002317 }
2318 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002319 case WLAN_HDD_FTM:
2320 {
2321 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2322
2323 if( NULL == pAdapter )
2324 return NULL;
2325 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
2326 * message while loading driver in FTM mode. */
2327 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
2328 pAdapter->device_mode = session_type;
2329 status = hdd_register_interface( pAdapter, rtnl_held );
2330 }
2331 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002332 default:
2333 {
2334 VOS_ASSERT(0);
2335 return NULL;
2336 }
2337 }
2338
2339
2340 if( VOS_STATUS_SUCCESS == status )
2341 {
2342 //Add it to the hdd's session list.
2343 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
2344 if( NULL == pHddAdapterNode )
2345 {
2346 status = VOS_STATUS_E_NOMEM;
2347 }
2348 else
2349 {
2350 pHddAdapterNode->pAdapter = pAdapter;
2351 status = hdd_add_adapter_back ( pHddCtx,
2352 pHddAdapterNode );
2353 }
2354 }
2355
2356 if( VOS_STATUS_SUCCESS != status )
2357 {
2358 if( NULL != pAdapter )
2359 {
2360 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
2361 pAdapter = NULL;
2362 }
2363 if( NULL != pHddAdapterNode )
2364 {
2365 vos_mem_free( pHddAdapterNode );
2366 }
2367
2368 goto resume_bmps;
2369 }
2370
2371 if(VOS_STATUS_SUCCESS == status)
2372 {
2373 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
2374
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07002375 //Initialize the WoWL service
2376 if(!hdd_init_wowl(pAdapter))
2377 {
2378 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
2379 goto err_free_netdev;
2380 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002381 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002382 return pAdapter;
2383
2384err_free_netdev:
2385 free_netdev(pAdapter->dev);
2386 wlan_hdd_release_intf_addr( pHddCtx,
2387 pAdapter->macAddressCurrent.bytes );
2388
2389resume_bmps:
2390 //If bmps disabled enable it
2391 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
2392 {
2393 hdd_enable_bmps_imps(pHddCtx);
2394 }
2395 return NULL;
2396}
2397
2398VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
2399 tANI_U8 rtnl_held )
2400{
2401 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
2402 VOS_STATUS status;
2403
2404 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
2405 if( VOS_STATUS_SUCCESS != status )
2406 return status;
2407
2408 while ( pCurrent->pAdapter != pAdapter )
2409 {
2410 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
2411 if( VOS_STATUS_SUCCESS != status )
2412 break;
2413
2414 pCurrent = pNext;
2415 }
2416 pAdapterNode = pCurrent;
2417 if( VOS_STATUS_SUCCESS == status )
2418 {
2419 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2420 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
2421 hdd_remove_adapter( pHddCtx, pAdapterNode );
2422 vos_mem_free( pAdapterNode );
2423
Jeff Johnson295189b2012-06-20 16:38:30 -07002424
2425 /* If there is a single session of STA/P2P client, re-enable BMPS */
2426 if ((!vos_concurrent_sessions_running()) &&
2427 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
2428 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
2429 {
2430 hdd_enable_bmps_imps(pHddCtx);
2431 }
2432
2433 return VOS_STATUS_SUCCESS;
2434 }
2435
2436 return VOS_STATUS_E_FAILURE;
2437}
2438
2439VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
2440{
2441 hdd_adapter_list_node_t *pHddAdapterNode;
2442 VOS_STATUS status;
2443
2444 ENTER();
2445
2446 do
2447 {
2448 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
2449 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
2450 {
2451 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
2452 vos_mem_free( pHddAdapterNode );
2453 }
2454 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
2455
2456 EXIT();
2457
2458 return VOS_STATUS_SUCCESS;
2459}
2460
2461void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
2462{
2463 v_U8_t addIE[1] = {0};
2464
2465 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2466 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
2467 eANI_BOOLEAN_FALSE) )
2468 {
2469 hddLog(LOGE,
2470 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
2471 }
2472
2473 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2474 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
2475 eANI_BOOLEAN_FALSE) )
2476 {
2477 hddLog(LOGE,
2478 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
2479 }
2480
2481 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2482 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
2483 eANI_BOOLEAN_FALSE) )
2484 {
2485 hddLog(LOGE,
2486 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
2487 }
2488}
2489
2490VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2491{
2492 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2493 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2494 union iwreq_data wrqu;
2495
2496 ENTER();
2497
2498 switch(pAdapter->device_mode)
2499 {
2500 case WLAN_HDD_INFRA_STATION:
2501 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002502 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002503 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
2504 {
2505 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
2506 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
2507 pAdapter->sessionId,
2508 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
2509 else
2510 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
2511 pAdapter->sessionId,
2512 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2513 //success implies disconnect command got queued up successfully
2514 if(halStatus == eHAL_STATUS_SUCCESS)
2515 {
2516 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
2517 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2518 }
2519 memset(&wrqu, '\0', sizeof(wrqu));
2520 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2521 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2522 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2523 }
2524 else
2525 {
2526 hdd_abort_mac_scan(pHddCtx);
2527 }
2528
2529 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
2530 {
2531 INIT_COMPLETION(pAdapter->session_close_comp_var);
2532 if (eHAL_STATUS_SUCCESS ==
2533 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
2534 hdd_smeCloseSessionCallback, pAdapter))
2535 {
2536 //Block on a completion variable. Can't wait forever though.
2537 wait_for_completion_interruptible_timeout(
2538 &pAdapter->session_close_comp_var,
2539 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2540 }
2541 }
2542
2543 break;
2544
2545 case WLAN_HDD_SOFTAP:
2546 case WLAN_HDD_P2P_GO:
2547 //Any softap specific cleanup here...
2548 mutex_lock(&pHddCtx->sap_lock);
2549 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2550 {
2551 VOS_STATUS status;
2552 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2553
2554 //Stop Bss.
2555 status = WLANSAP_StopBss(pHddCtx->pvosContext);
2556 if (VOS_IS_STATUS_SUCCESS(status))
2557 {
2558 hdd_hostapd_state_t *pHostapdState =
2559 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2560
2561 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2562
2563 if (!VOS_IS_STATUS_SUCCESS(status))
2564 {
2565 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002566 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002567 }
2568 }
2569 else
2570 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002571 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002572 }
2573 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2574
2575 if (eHAL_STATUS_FAILURE ==
2576 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
2577 0, NULL, eANI_BOOLEAN_FALSE))
2578 {
2579 hddLog(LOGE,
2580 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002581 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002582 }
2583
2584 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2585 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2586 eANI_BOOLEAN_FALSE) )
2587 {
2588 hddLog(LOGE,
2589 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
2590 }
2591
2592 // Reset WNI_CFG_PROBE_RSP Flags
2593 wlan_hdd_reset_prob_rspies(pAdapter);
2594 kfree(pAdapter->sessionCtx.ap.beacon);
2595 pAdapter->sessionCtx.ap.beacon = NULL;
2596 }
2597 mutex_unlock(&pHddCtx->sap_lock);
2598 break;
2599 case WLAN_HDD_MONITOR:
2600 break;
2601 default:
2602 break;
2603 }
2604
2605 EXIT();
2606 return VOS_STATUS_SUCCESS;
2607}
2608
2609VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
2610{
2611 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2612 VOS_STATUS status;
2613 hdd_adapter_t *pAdapter;
2614
2615 ENTER();
2616
2617 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2618
2619 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2620 {
2621 pAdapter = pAdapterNode->pAdapter;
2622 netif_tx_disable(pAdapter->dev);
2623 netif_carrier_off(pAdapter->dev);
2624
2625 hdd_stop_adapter( pHddCtx, pAdapter );
2626
2627 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2628 pAdapterNode = pNext;
2629 }
2630
2631 EXIT();
2632
2633 return VOS_STATUS_SUCCESS;
2634}
2635
2636VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
2637{
2638 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2639 VOS_STATUS status;
2640 hdd_adapter_t *pAdapter;
2641
2642 ENTER();
2643
2644 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2645
2646 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2647 {
2648 pAdapter = pAdapterNode->pAdapter;
2649 netif_tx_disable(pAdapter->dev);
2650 netif_carrier_off(pAdapter->dev);
2651
2652 //Record whether STA is associated
2653 pAdapter->sessionCtx.station.bSendDisconnect =
2654 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
2655 VOS_TRUE : VOS_FALSE;
2656
2657 hdd_deinit_tx_rx(pAdapter);
2658 hdd_wmm_adapter_close(pAdapter);
2659
2660 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2661 pAdapterNode = pNext;
2662 }
2663
2664 EXIT();
2665
2666 return VOS_STATUS_SUCCESS;
2667}
2668
2669VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
2670{
2671 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2672 VOS_STATUS status;
2673 hdd_adapter_t *pAdapter;
2674 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
2675
2676 ENTER();
2677
2678 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2679
2680 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2681 {
2682 pAdapter = pAdapterNode->pAdapter;
2683
2684 switch(pAdapter->device_mode)
2685 {
2686 case WLAN_HDD_INFRA_STATION:
2687 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002688 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002689 hdd_init_station_mode(pAdapter);
2690 /* Open the gates for HDD to receive Wext commands */
2691 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002692 pHddCtx->scan_info.mScanPending = FALSE;
2693 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002694
2695 //Trigger the initial scan
2696 hdd_wlan_initial_scan(pAdapter);
2697
2698 //Indicate disconnect event to supplicant if associated previously
2699 if(pAdapter->sessionCtx.station.bSendDisconnect)
2700 {
2701 union iwreq_data wrqu;
2702 memset(&wrqu, '\0', sizeof(wrqu));
2703 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2704 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2705 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2706 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
2707
Jeff Johnson295189b2012-06-20 16:38:30 -07002708 /* indicate disconnected event to nl80211 */
2709 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
2710 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002711 }
2712 break;
2713
2714 case WLAN_HDD_SOFTAP:
2715 /* softAP can handle SSR */
2716 break;
2717
2718 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002719 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
2720 __func__);
2721 /* event supplicant to restart */
2722 cfg80211_del_sta(pAdapter->dev,
2723 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002724 break;
2725
2726 case WLAN_HDD_MONITOR:
2727 /* monitor interface start */
2728 break;
2729 default:
2730 break;
2731 }
2732
2733 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2734 pAdapterNode = pNext;
2735 }
2736
2737 EXIT();
2738
2739 return VOS_STATUS_SUCCESS;
2740}
2741
2742VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
2743{
2744 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2745 hdd_adapter_t *pAdapter;
2746 VOS_STATUS status;
2747 v_U32_t roamId;
2748
2749 ENTER();
2750
2751 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2752
2753 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2754 {
2755 pAdapter = pAdapterNode->pAdapter;
2756
2757 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
2758 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
2759 {
2760 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2761 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2762
2763 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2764 init_completion(&pAdapter->disconnect_comp_var);
2765 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
2766 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2767
2768 wait_for_completion_interruptible_timeout(
2769 &pAdapter->disconnect_comp_var,
2770 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2771
2772 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
2773 pHddCtx->isAmpAllowed = VOS_FALSE;
2774 sme_RoamConnect(pHddCtx->hHal,
2775 pAdapter->sessionId, &(pWextState->roamProfile),
2776 &roamId);
2777 }
2778
2779 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2780 pAdapterNode = pNext;
2781 }
2782
2783 EXIT();
2784
2785 return VOS_STATUS_SUCCESS;
2786}
2787
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002788bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07002789{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002790 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07002791}
2792
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002793/* Once SSR is disabled then it cannot be set. */
2794void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07002795{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002796 if (HDD_SSR_DISABLED == isSsrRequired)
2797 return;
2798
Jeff Johnson295189b2012-06-20 16:38:30 -07002799 isSsrRequired = value;
2800}
2801
2802VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
2803 hdd_adapter_list_node_t** ppAdapterNode)
2804{
2805 VOS_STATUS status;
2806 spin_lock(&pHddCtx->hddAdapters.lock);
2807 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
2808 (hdd_list_node_t**) ppAdapterNode );
2809 spin_unlock(&pHddCtx->hddAdapters.lock);
2810 return status;
2811}
2812
2813VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
2814 hdd_adapter_list_node_t* pAdapterNode,
2815 hdd_adapter_list_node_t** pNextAdapterNode)
2816{
2817 VOS_STATUS status;
2818 spin_lock(&pHddCtx->hddAdapters.lock);
2819 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
2820 (hdd_list_node_t*) pAdapterNode,
2821 (hdd_list_node_t**)pNextAdapterNode );
2822
2823 spin_unlock(&pHddCtx->hddAdapters.lock);
2824 return status;
2825}
2826
2827VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
2828 hdd_adapter_list_node_t* pAdapterNode)
2829{
2830 VOS_STATUS status;
2831 spin_lock(&pHddCtx->hddAdapters.lock);
2832 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
2833 &pAdapterNode->node );
2834 spin_unlock(&pHddCtx->hddAdapters.lock);
2835 return status;
2836}
2837
2838VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
2839 hdd_adapter_list_node_t** ppAdapterNode)
2840{
2841 VOS_STATUS status;
2842 spin_lock(&pHddCtx->hddAdapters.lock);
2843 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
2844 (hdd_list_node_t**) ppAdapterNode );
2845 spin_unlock(&pHddCtx->hddAdapters.lock);
2846 return status;
2847}
2848
2849VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
2850 hdd_adapter_list_node_t* pAdapterNode)
2851{
2852 VOS_STATUS status;
2853 spin_lock(&pHddCtx->hddAdapters.lock);
2854 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
2855 (hdd_list_node_t*) pAdapterNode );
2856 spin_unlock(&pHddCtx->hddAdapters.lock);
2857 return status;
2858}
2859
2860VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
2861 hdd_adapter_list_node_t* pAdapterNode)
2862{
2863 VOS_STATUS status;
2864 spin_lock(&pHddCtx->hddAdapters.lock);
2865 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
2866 (hdd_list_node_t*) pAdapterNode );
2867 spin_unlock(&pHddCtx->hddAdapters.lock);
2868 return status;
2869}
2870
2871hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
2872 tSirMacAddr macAddr )
2873{
2874 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2875 hdd_adapter_t *pAdapter;
2876 VOS_STATUS status;
2877
2878 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2879
2880 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2881 {
2882 pAdapter = pAdapterNode->pAdapter;
2883
2884 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
2885 macAddr, sizeof(tSirMacAddr) ) )
2886 {
2887 return pAdapter;
2888 }
2889 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2890 pAdapterNode = pNext;
2891 }
2892
2893 return NULL;
2894
2895}
2896
2897hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
2898{
2899 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2900 hdd_adapter_t *pAdapter;
2901 VOS_STATUS status;
2902
2903 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2904
2905 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2906 {
2907 pAdapter = pAdapterNode->pAdapter;
2908
2909 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
2910 IFNAMSIZ ) )
2911 {
2912 return pAdapter;
2913 }
2914 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2915 pAdapterNode = pNext;
2916 }
2917
2918 return NULL;
2919
2920}
2921
2922hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
2923{
2924 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2925 hdd_adapter_t *pAdapter;
2926 VOS_STATUS status;
2927
2928 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2929
2930 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2931 {
2932 pAdapter = pAdapterNode->pAdapter;
2933
2934 if( pAdapter && (mode == pAdapter->device_mode) )
2935 {
2936 return pAdapter;
2937 }
2938 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2939 pAdapterNode = pNext;
2940 }
2941
2942 return NULL;
2943
2944}
2945
2946//Remove this function later
2947hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
2948{
2949 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2950 hdd_adapter_t *pAdapter;
2951 VOS_STATUS status;
2952
2953 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2954
2955 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2956 {
2957 pAdapter = pAdapterNode->pAdapter;
2958
2959 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
2960 {
2961 return pAdapter;
2962 }
2963
2964 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2965 pAdapterNode = pNext;
2966 }
2967
2968 return NULL;
2969
2970}
2971
Jeff Johnson295189b2012-06-20 16:38:30 -07002972/**---------------------------------------------------------------------------
2973
2974 \brief hdd_set_monitor_tx_adapter() -
2975
2976 This API initializes the adapter to be used while transmitting on monitor
2977 adapter.
2978
2979 \param - pHddCtx - Pointer to the HDD context.
2980 pAdapter - Adapter that will used for TX. This can be NULL.
2981 \return - None.
2982 --------------------------------------------------------------------------*/
2983void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2984{
2985 hdd_adapter_t *pMonAdapter;
2986
2987 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
2988
2989 if( NULL != pMonAdapter )
2990 {
2991 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
2992 }
2993}
Jeff Johnson295189b2012-06-20 16:38:30 -07002994/**---------------------------------------------------------------------------
2995
2996 \brief hdd_select_queue() -
2997
2998 This API returns the operating channel of the requested device mode
2999
3000 \param - pHddCtx - Pointer to the HDD context.
3001 - mode - Device mode for which operating channel is required
3002 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
3003 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
3004 \return - channel number. "0" id the requested device is not found OR it is not connected.
3005 --------------------------------------------------------------------------*/
3006v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
3007{
3008 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3009 VOS_STATUS status;
3010 hdd_adapter_t *pAdapter;
3011 v_U8_t operatingChannel = 0;
3012
3013 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3014
3015 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3016 {
3017 pAdapter = pAdapterNode->pAdapter;
3018
3019 if( mode == pAdapter->device_mode )
3020 {
3021 switch(pAdapter->device_mode)
3022 {
3023 case WLAN_HDD_INFRA_STATION:
3024 case WLAN_HDD_P2P_CLIENT:
3025 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3026 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
3027 break;
3028 case WLAN_HDD_SOFTAP:
3029 case WLAN_HDD_P2P_GO:
3030 /*softap connection info */
3031 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3032 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
3033 break;
3034 default:
3035 break;
3036 }
3037
3038 break; //Found the device of interest. break the loop
3039 }
3040
3041 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3042 pAdapterNode = pNext;
3043 }
3044 return operatingChannel;
3045}
3046
3047#ifdef WLAN_FEATURE_PACKET_FILTERING
3048/**---------------------------------------------------------------------------
3049
3050 \brief hdd_set_multicast_list() -
3051
3052 This used to set the multicast address list.
3053
3054 \param - dev - Pointer to the WLAN device.
3055 - skb - Pointer to OS packet (sk_buff).
3056 \return - success/fail
3057
3058 --------------------------------------------------------------------------*/
3059static void hdd_set_multicast_list(struct net_device *dev)
3060{
3061 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07003062 int mc_count;
3063 int i = 0;
3064 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303065
3066 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07003067 {
3068 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303069 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003070 return;
3071 }
3072
3073 if (dev->flags & IFF_ALLMULTI)
3074 {
3075 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003076 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303077 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003078 }
3079 else
3080 {
3081 mc_count = netdev_mc_count(dev);
3082 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003083 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07003084 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
3085 {
3086 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003087 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303088 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003089 return;
3090 }
3091
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303092 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07003093
3094 netdev_for_each_mc_addr(ha, dev) {
3095 if (i == mc_count)
3096 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303097 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
3098 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
3099 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003100 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303101 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07003102 i++;
3103 }
3104 }
3105 return;
3106}
3107#endif
3108
3109/**---------------------------------------------------------------------------
3110
3111 \brief hdd_select_queue() -
3112
3113 This function is registered with the Linux OS for network
3114 core to decide which queue to use first.
3115
3116 \param - dev - Pointer to the WLAN device.
3117 - skb - Pointer to OS packet (sk_buff).
3118 \return - ac, Queue Index/access category corresponding to UP in IP header
3119
3120 --------------------------------------------------------------------------*/
3121v_U16_t hdd_select_queue(struct net_device *dev,
3122 struct sk_buff *skb)
3123{
3124 return hdd_wmm_select_queue(dev, skb);
3125}
3126
3127
3128/**---------------------------------------------------------------------------
3129
3130 \brief hdd_wlan_initial_scan() -
3131
3132 This function triggers the initial scan
3133
3134 \param - pAdapter - Pointer to the HDD adapter.
3135
3136 --------------------------------------------------------------------------*/
3137void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
3138{
3139 tCsrScanRequest scanReq;
3140 tCsrChannelInfo channelInfo;
3141 eHalStatus halStatus;
3142 unsigned long scanId;
3143 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3144
3145 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
3146 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
3147 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
3148
3149 if(sme_Is11dSupported(pHddCtx->hHal))
3150 {
3151 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
3152 if ( HAL_STATUS_SUCCESS( halStatus ) )
3153 {
3154 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
3155 if( !scanReq.ChannelInfo.ChannelList )
3156 {
3157 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
3158 vos_mem_free(channelInfo.ChannelList);
3159 return;
3160 }
3161 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
3162 channelInfo.numOfChannels);
3163 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
3164 vos_mem_free(channelInfo.ChannelList);
3165 }
3166
3167 scanReq.scanType = eSIR_PASSIVE_SCAN;
3168 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
3169 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
3170 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
3171 }
3172 else
3173 {
3174 scanReq.scanType = eSIR_ACTIVE_SCAN;
3175 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
3176 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
3177 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
3178 }
3179
3180 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
3181 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3182 {
3183 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
3184 __func__, halStatus );
3185 }
3186
3187 if(sme_Is11dSupported(pHddCtx->hHal))
3188 vos_mem_free(scanReq.ChannelInfo.ChannelList);
3189}
3190
3191struct fullPowerContext
3192{
3193 struct completion completion;
3194 unsigned int magic;
3195};
3196#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
3197
3198/**---------------------------------------------------------------------------
3199
3200 \brief hdd_full_power_callback() - HDD full power callback function
3201
3202 This is the function invoked by SME to inform the result of a full power
3203 request issued by HDD
3204
3205 \param - callbackcontext - Pointer to cookie
3206 \param - status - result of request
3207
3208 \return - None
3209
3210 --------------------------------------------------------------------------*/
3211static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
3212{
3213 struct fullPowerContext *pContext = callbackContext;
3214
3215 hddLog(VOS_TRACE_LEVEL_INFO,
3216 "%s: context = %p, status = %d", pContext, status);
3217
3218 if (NULL == callbackContext)
3219 {
3220 hddLog(VOS_TRACE_LEVEL_ERROR,
3221 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003222 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07003223 return;
3224 }
3225
3226 /* there is a race condition that exists between this callback function
3227 and the caller since the caller could time out either before or
3228 while this code is executing. we'll assume the timeout hasn't
3229 occurred, but we'll verify that right before we save our work */
3230
3231 if (POWER_CONTEXT_MAGIC != pContext->magic)
3232 {
3233 /* the caller presumably timed out so there is nothing we can do */
3234 hddLog(VOS_TRACE_LEVEL_WARN,
3235 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003236 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07003237 return;
3238 }
3239
3240 /* the race is on. caller could have timed out immediately after
3241 we verified the magic, but if so, caller will wait a short time
3242 for us to notify the caller, so the context will stay valid */
3243 complete(&pContext->completion);
3244}
3245
3246/**---------------------------------------------------------------------------
3247
3248 \brief hdd_wlan_exit() - HDD WLAN exit function
3249
3250 This is the driver exit point (invoked during rmmod)
3251
3252 \param - pHddCtx - Pointer to the HDD Context
3253
3254 \return - None
3255
3256 --------------------------------------------------------------------------*/
3257void hdd_wlan_exit(hdd_context_t *pHddCtx)
3258{
3259 eHalStatus halStatus;
3260 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
3261 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05303262 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003263 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003264 struct fullPowerContext powerContext;
3265 long lrc;
3266
3267 ENTER();
3268
Jeff Johnson88ba7742013-02-27 14:36:02 -08003269 if (VOS_FTM_MODE != hdd_get_conparam())
3270 {
3271 // Unloading, restart logic is no more required.
3272 wlan_hdd_restart_deinit(pHddCtx);
3273 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003274
Jeff Johnson295189b2012-06-20 16:38:30 -07003275 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003276 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003277 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003278 {
3279 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
3280 WLAN_HDD_INFRA_STATION);
3281 if (pAdapter == NULL)
3282 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3283
3284 if (pAdapter != NULL)
3285 {
3286 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
3287 hdd_UnregisterWext(pAdapter->dev);
3288 }
3289 }
3290 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003291
Jeff Johnson295189b2012-06-20 16:38:30 -07003292 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08003293 {
3294 wlan_hdd_ftm_close(pHddCtx);
3295 goto free_hdd_ctx;
3296 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003297 //Stop the Interface TX queue.
3298 //netif_tx_disable(pWlanDev);
3299 //netif_carrier_off(pWlanDev);
3300
Jeff Johnson295189b2012-06-20 16:38:30 -07003301 if (VOS_STA_SAP_MODE == hdd_get_conparam())
3302 {
3303 pAdapter = hdd_get_adapter(pHddCtx,
3304 WLAN_HDD_SOFTAP);
3305 }
3306 else
3307 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003308 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003309 {
3310 pAdapter = hdd_get_adapter(pHddCtx,
3311 WLAN_HDD_INFRA_STATION);
3312 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003313 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003314 /* DeRegister with platform driver as client for Suspend/Resume */
3315 vosStatus = hddDeregisterPmOps(pHddCtx);
3316 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3317 {
3318 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
3319 VOS_ASSERT(0);
3320 }
3321
3322 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
3323 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3324 {
3325 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
3326 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003327
3328 // Cancel any outstanding scan requests. We are about to close all
3329 // of our adapters, but an adapter structure is what SME passes back
3330 // to our callback function. Hence if there are any outstanding scan
3331 // requests then there is a race condition between when the adapter
3332 // is closed and when the callback is invoked. We try to resolve that
3333 // race condition here by canceling any outstanding scans before we
3334 // close the adapters.
3335 // Note that the scans may be cancelled in an asynchronous manner, so
3336 // ideally there needs to be some kind of synchronization. Rather than
3337 // introduce a new synchronization here, we will utilize the fact that
3338 // we are about to Request Full Power, and since that is synchronized,
3339 // the expectation is that by the time Request Full Power has completed,
3340 // all scans will be cancelled.
3341 hdd_abort_mac_scan( pHddCtx );
3342
3343 //Disable IMPS/BMPS as we do not want the device to enter any power
3344 //save mode during shutdown
3345 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3346 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3347 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
3348
3349 //Ensure that device is in full power as we will touch H/W during vos_Stop
3350 init_completion(&powerContext.completion);
3351 powerContext.magic = POWER_CONTEXT_MAGIC;
3352
3353 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
3354 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
3355
3356 if (eHAL_STATUS_SUCCESS != halStatus)
3357 {
3358 if (eHAL_STATUS_PMC_PENDING == halStatus)
3359 {
3360 /* request was sent -- wait for the response */
3361 lrc = wait_for_completion_interruptible_timeout(
3362 &powerContext.completion,
3363 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
3364 /* either we have a response or we timed out
3365 either way, first invalidate our magic */
3366 powerContext.magic = 0;
3367 if (lrc <= 0)
3368 {
3369 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003370 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07003371 /* there is a race condition such that the callback
3372 function could be executing at the same time we are. of
3373 primary concern is if the callback function had already
3374 verified the "magic" but hasn't yet set the completion
3375 variable. Since the completion variable is on our
3376 stack, we'll delay just a bit to make sure the data is
3377 still valid if that is the case */
3378 msleep(50);
3379 }
3380 }
3381 else
3382 {
3383 hddLog(VOS_TRACE_LEVEL_ERROR,
3384 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003385 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07003386 VOS_ASSERT(0);
3387 /* continue -- need to clean up as much as possible */
3388 }
3389 }
3390
3391 // Unregister the Net Device Notifier
3392 unregister_netdevice_notifier(&hdd_netdev_notifier);
3393
Jeff Johnson295189b2012-06-20 16:38:30 -07003394 hdd_stop_all_adapters( pHddCtx );
3395
Jeff Johnson295189b2012-06-20 16:38:30 -07003396#ifdef WLAN_BTAMP_FEATURE
3397 vosStatus = WLANBAP_Stop(pVosContext);
3398 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3399 {
3400 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3401 "%s: Failed to stop BAP",__func__);
3402 }
3403#endif //WLAN_BTAMP_FEATURE
3404
3405 //Stop all the modules
3406 vosStatus = vos_stop( pVosContext );
3407 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3408 {
3409 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3410 "%s: Failed to stop VOSS",__func__);
3411 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3412 }
3413
Jeff Johnson295189b2012-06-20 16:38:30 -07003414 //Assert Deep sleep signal now to put Libra HW in lowest power state
3415 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
3416 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3417
3418 //Vote off any PMIC voltage supplies
3419 vos_chipPowerDown(NULL, NULL, NULL);
3420
3421 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
3422
3423 //Clean up HDD Nlink Service
3424 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
3425 nl_srv_exit();
3426
3427 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07003428 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003429
3430 //Close the scheduler before calling vos_close to make sure no thread is
3431 // scheduled after the each module close is called i.e after all the data
3432 // structures are freed.
3433 vosStatus = vos_sched_close( pVosContext );
3434 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
3435 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
3436 "%s: Failed to close VOSS Scheduler",__func__);
3437 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3438 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003439#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07003440#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3441 /* Destroy the wake lock */
3442 wake_lock_destroy(&pHddCtx->rx_wake_lock);
3443#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08003444 /* Destroy the wake lock */
3445 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003446#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003447
3448 //Close VOSS
3449 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
3450 vos_close(pVosContext);
3451
Jeff Johnson295189b2012-06-20 16:38:30 -07003452 //Close Watchdog
3453 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3454 vos_watchdog_close(pVosContext);
3455
3456 /* Cancel the vote for XO Core ON.
3457 * This is done here to ensure there is no race condition since MC, TX and WD threads have
3458 * exited at this point
3459 */
3460 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
3461 " when WLAN is turned OFF\n");
3462 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
3463 {
3464 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
3465 " Not returning failure."
3466 " Power consumed will be high\n");
3467 }
3468
3469 hdd_close_all_adapters( pHddCtx );
3470
3471
3472 //Free up dynamically allocated members inside HDD Adapter
3473 kfree(pHddCtx->cfg_ini);
3474 pHddCtx->cfg_ini= NULL;
3475
3476 /* free the power on lock from platform driver */
3477 if (free_riva_power_on_lock("wlan"))
3478 {
3479 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
3480 __func__);
3481 }
3482
Jeff Johnson88ba7742013-02-27 14:36:02 -08003483free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08003484 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07003485 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07003486 if (hdd_is_ssr_required())
3487 {
3488 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07003489 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07003490 msleep(5000);
3491 }
3492 hdd_set_ssr_required (VOS_FALSE);
3493}
3494
3495
3496/**---------------------------------------------------------------------------
3497
3498 \brief hdd_update_config_from_nv() - Function to update the contents of
3499 the running configuration with parameters taken from NV storage
3500
3501 \param - pHddCtx - Pointer to the HDD global context
3502
3503 \return - VOS_STATUS_SUCCESS if successful
3504
3505 --------------------------------------------------------------------------*/
3506static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
3507{
Jeff Johnson295189b2012-06-20 16:38:30 -07003508 v_BOOL_t itemIsValid = VOS_FALSE;
3509 VOS_STATUS status;
3510 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
3511 v_U8_t macLoop;
3512
3513 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
3514 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
3515 if(status != VOS_STATUS_SUCCESS)
3516 {
3517 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
3518 return VOS_STATUS_E_FAILURE;
3519 }
3520
3521 if (itemIsValid == VOS_TRUE)
3522 {
3523 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
3524 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
3525 VOS_MAX_CONCURRENCY_PERSONA);
3526 if(status != VOS_STATUS_SUCCESS)
3527 {
3528 /* Get MAC from NV fail, not update CFG info
3529 * INI MAC value will be used for MAC setting */
3530 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
3531 return VOS_STATUS_E_FAILURE;
3532 }
3533
3534 /* If first MAC is not valid, treat all others are not valid
3535 * Then all MACs will be got from ini file */
3536 if(vos_is_macaddr_zero(&macFromNV[0]))
3537 {
3538 /* MAC address in NV file is not configured yet */
3539 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
3540 return VOS_STATUS_E_INVAL;
3541 }
3542
3543 /* Get MAC address from NV, update CFG info */
3544 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
3545 {
3546 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
3547 {
3548 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
3549 /* This MAC is not valid, skip it
3550 * This MAC will be got from ini file */
3551 }
3552 else
3553 {
3554 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
3555 (v_U8_t *)&macFromNV[macLoop].bytes[0],
3556 VOS_MAC_ADDR_SIZE);
3557 }
3558 }
3559 }
3560 else
3561 {
3562 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
3563 return VOS_STATUS_E_FAILURE;
3564 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003565
Jeff Johnson295189b2012-06-20 16:38:30 -07003566
3567 return VOS_STATUS_SUCCESS;
3568}
3569
3570/**---------------------------------------------------------------------------
3571
3572 \brief hdd_post_voss_start_config() - HDD post voss start config helper
3573
3574 \param - pAdapter - Pointer to the HDD
3575
3576 \return - None
3577
3578 --------------------------------------------------------------------------*/
3579VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
3580{
3581 eHalStatus halStatus;
3582 v_U32_t listenInterval;
3583
Jeff Johnson295189b2012-06-20 16:38:30 -07003584
3585 // Send ready indication to the HDD. This will kick off the MAC
3586 // into a 'running' state and should kick off an initial scan.
3587 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
3588 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3589 {
3590 hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
3591 "code %08d [x%08x]",__func__, halStatus, halStatus );
3592 return VOS_STATUS_E_FAILURE;
3593 }
3594
3595 // Set default LI into HDD context,
3596 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
3597 // And RIVA will crash
3598 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
3599 pHddCtx->hdd_actual_LI_value = listenInterval;
3600
3601 return VOS_STATUS_SUCCESS;
3602}
3603
Jeff Johnson295189b2012-06-20 16:38:30 -07003604/* wake lock APIs for HDD */
3605void hdd_prevent_suspend(void)
3606{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003607#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003608 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003609#else
3610 wcnss_prevent_suspend();
3611#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003612}
3613
3614void hdd_allow_suspend(void)
3615{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003616#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003617 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003618#else
3619 wcnss_allow_suspend();
3620#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003621}
3622
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003623void hdd_allow_suspend_timeout(v_U32_t timeout)
3624{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003625#ifdef WLAN_OPEN_SOURCE
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003626 wake_lock_timeout(&wlan_wake_lock, timeout);
3627#else
3628 /* Do nothing as there is no API in wcnss for timeout*/
3629#endif
3630}
3631
Jeff Johnson295189b2012-06-20 16:38:30 -07003632/**---------------------------------------------------------------------------
3633
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003634 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
3635 information between Host and Riva
3636
3637 This function gets reported version of FW
3638 It also finds the version of Riva headers used to compile the host
3639 It compares the above two and prints a warning if they are different
3640 It gets the SW and HW version string
3641 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
3642 indicating the features they support through a bitmap
3643
3644 \param - pHddCtx - Pointer to HDD context
3645
3646 \return - void
3647
3648 --------------------------------------------------------------------------*/
3649
3650void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
3651{
3652
3653 tSirVersionType versionCompiled;
3654 tSirVersionType versionReported;
3655 tSirVersionString versionString;
3656 tANI_U8 fwFeatCapsMsgSupported = 0;
3657 VOS_STATUS vstatus;
3658
3659 /* retrieve and display WCNSS version information */
3660 do {
3661
3662 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
3663 &versionCompiled);
3664 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3665 {
3666 hddLog(VOS_TRACE_LEVEL_FATAL,
3667 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003668 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003669 break;
3670 }
3671
3672 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
3673 &versionReported);
3674 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3675 {
3676 hddLog(VOS_TRACE_LEVEL_FATAL,
3677 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003678 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003679 break;
3680 }
3681
3682 if ((versionCompiled.major != versionReported.major) ||
3683 (versionCompiled.minor != versionReported.minor) ||
3684 (versionCompiled.version != versionReported.version) ||
3685 (versionCompiled.revision != versionReported.revision))
3686 {
3687 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
3688 "Host expected %u.%u.%u.%u\n",
3689 WLAN_MODULE_NAME,
3690 (int)versionReported.major,
3691 (int)versionReported.minor,
3692 (int)versionReported.version,
3693 (int)versionReported.revision,
3694 (int)versionCompiled.major,
3695 (int)versionCompiled.minor,
3696 (int)versionCompiled.version,
3697 (int)versionCompiled.revision);
3698 }
3699 else
3700 {
3701 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
3702 WLAN_MODULE_NAME,
3703 (int)versionReported.major,
3704 (int)versionReported.minor,
3705 (int)versionReported.version,
3706 (int)versionReported.revision);
3707 }
3708
3709 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
3710 versionString,
3711 sizeof(versionString));
3712 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3713 {
3714 hddLog(VOS_TRACE_LEVEL_FATAL,
3715 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003716 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003717 break;
3718 }
3719
3720 pr_info("%s: WCNSS software version %s\n",
3721 WLAN_MODULE_NAME, versionString);
3722
3723 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
3724 versionString,
3725 sizeof(versionString));
3726 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3727 {
3728 hddLog(VOS_TRACE_LEVEL_FATAL,
3729 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003730 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003731 break;
3732 }
3733
3734 pr_info("%s: WCNSS hardware version %s\n",
3735 WLAN_MODULE_NAME, versionString);
3736
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003737 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
3738 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003739 send the message only if it the riva is 1.1
3740 minor numbers for different riva branches:
3741 0 -> (1.0)Mainline Build
3742 1 -> (1.1)Mainline Build
3743 2->(1.04) Stability Build
3744 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003745 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003746 ((versionReported.minor>=1) && (versionReported.version>=1)))
3747 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
3748 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003749
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003750 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08003751 {
3752#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
3753 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
3754 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
3755#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003756 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08003757 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003758
3759 } while (0);
3760
3761}
3762
3763/**---------------------------------------------------------------------------
3764
Jeff Johnson295189b2012-06-20 16:38:30 -07003765 \brief hdd_wlan_startup() - HDD init function
3766
3767 This is the driver startup code executed once a WLAN device has been detected
3768
3769 \param - dev - Pointer to the underlying device
3770
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003771 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07003772
3773 --------------------------------------------------------------------------*/
3774
3775int hdd_wlan_startup(struct device *dev )
3776{
3777 VOS_STATUS status;
3778 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003779 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003780 hdd_context_t *pHddCtx = NULL;
3781 v_CONTEXT_t pVosContext= NULL;
3782#ifdef WLAN_BTAMP_FEATURE
3783 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
3784 WLANBAP_ConfigType btAmpConfig;
3785 hdd_config_t *pConfig;
3786#endif
3787 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07003788 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003789
3790 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07003791 /*
3792 * cfg80211: wiphy allocation
3793 */
3794 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
3795
3796 if(wiphy == NULL)
3797 {
3798 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003799 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003800 }
3801
3802 pHddCtx = wiphy_priv(wiphy);
3803
Jeff Johnson295189b2012-06-20 16:38:30 -07003804 //Initialize the adapter context to zeros.
3805 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
3806
Jeff Johnson295189b2012-06-20 16:38:30 -07003807 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003808 hdd_prevent_suspend();
3809 pHddCtx->isLoadUnloadInProgress = TRUE;
3810
3811 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
3812
3813 /*Get vos context here bcoz vos_open requires it*/
3814 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
3815
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08003816 if(pVosContext == NULL)
3817 {
3818 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
3819 goto err_free_hdd_context;
3820 }
3821
Jeff Johnson295189b2012-06-20 16:38:30 -07003822 //Save the Global VOSS context in adapter context for future.
3823 pHddCtx->pvosContext = pVosContext;
3824
3825 //Save the adapter context in global context for future.
3826 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
3827
Jeff Johnson295189b2012-06-20 16:38:30 -07003828 pHddCtx->parent_dev = dev;
3829
3830 init_completion(&pHddCtx->full_pwr_comp_var);
3831 init_completion(&pHddCtx->standby_comp_var);
3832 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003833 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003834 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003835
3836 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
3837
3838 // Load all config first as TL config is needed during vos_open
3839 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
3840 if(pHddCtx->cfg_ini == NULL)
3841 {
3842 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
3843 goto err_free_hdd_context;
3844 }
3845
3846 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
3847
3848 // Read and parse the qcom_cfg.ini file
3849 status = hdd_parse_config_ini( pHddCtx );
3850 if ( VOS_STATUS_SUCCESS != status )
3851 {
3852 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
3853 __func__, WLAN_INI_FILE);
3854 goto err_config;
3855 }
3856
Jeff Johnson295189b2012-06-20 16:38:30 -07003857 /*
3858 * cfg80211: Initialization and registration ...
3859 */
3860 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
3861 {
3862 hddLog(VOS_TRACE_LEVEL_FATAL,
3863 "%s: wlan_hdd_cfg80211_register return failure", __func__);
3864 goto err_wiphy_reg;
3865 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003866
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003867 // Update VOS trace levels based upon the cfg.ini
3868 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
3869 pHddCtx->cfg_ini->vosTraceEnableBAP);
3870 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
3871 pHddCtx->cfg_ini->vosTraceEnableTL);
3872 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
3873 pHddCtx->cfg_ini->vosTraceEnableWDI);
3874 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
3875 pHddCtx->cfg_ini->vosTraceEnableHDD);
3876 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
3877 pHddCtx->cfg_ini->vosTraceEnableSME);
3878 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
3879 pHddCtx->cfg_ini->vosTraceEnablePE);
3880 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
3881 pHddCtx->cfg_ini->vosTraceEnableWDA);
3882 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
3883 pHddCtx->cfg_ini->vosTraceEnableSYS);
3884 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
3885 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003886 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
3887 pHddCtx->cfg_ini->vosTraceEnableSAP);
3888 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
3889 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003890
Jeff Johnson295189b2012-06-20 16:38:30 -07003891 // Update WDI trace levels based upon the cfg.ini
3892 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
3893 pHddCtx->cfg_ini->wdiTraceEnableDAL);
3894 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
3895 pHddCtx->cfg_ini->wdiTraceEnableCTL);
3896 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
3897 pHddCtx->cfg_ini->wdiTraceEnableDAT);
3898 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
3899 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003900
Jeff Johnson88ba7742013-02-27 14:36:02 -08003901 if (VOS_FTM_MODE == hdd_get_conparam())
3902 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003903 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
3904 {
3905 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
3906 goto err_free_hdd_context;
3907 }
3908 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
3909 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08003910 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003911
Jeff Johnson88ba7742013-02-27 14:36:02 -08003912 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07003913 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3914 {
3915 status = vos_watchdog_open(pVosContext,
3916 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
3917
3918 if(!VOS_IS_STATUS_SUCCESS( status ))
3919 {
3920 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003921 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07003922 }
3923 }
3924
3925 pHddCtx->isLogpInProgress = FALSE;
3926 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
3927
Jeff Johnson295189b2012-06-20 16:38:30 -07003928 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
3929 if(!VOS_IS_STATUS_SUCCESS(status))
3930 {
3931 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003932 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07003933 }
3934
Jeff Johnson295189b2012-06-20 16:38:30 -07003935 status = vos_open( &pVosContext, 0);
3936 if ( !VOS_IS_STATUS_SUCCESS( status ))
3937 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003938 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
3939 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07003940 }
3941
Jeff Johnson295189b2012-06-20 16:38:30 -07003942 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
3943
3944 if ( NULL == pHddCtx->hHal )
3945 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003946 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003947 goto err_vosclose;
3948 }
3949
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003950 status = vos_preStart( pHddCtx->pvosContext );
3951 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3952 {
3953 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
3954 goto err_vosclose;
3955 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003956
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003957 /* Note that the vos_preStart() sequence triggers the cfg download.
3958 The cfg download must occur before we update the SME config
3959 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07003960 status = hdd_set_sme_config( pHddCtx );
3961
3962 if ( VOS_STATUS_SUCCESS != status )
3963 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08003964 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
3965 goto err_vosclose;
3966 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003967
3968 //Initialize the WMM module
3969 status = hdd_wmm_init(pHddCtx);
3970 if (!VOS_IS_STATUS_SUCCESS(status))
3971 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003972 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003973 goto err_vosclose;
3974 }
3975
Jeff Johnson295189b2012-06-20 16:38:30 -07003976 /* In the integrated architecture we update the configuration from
3977 the INI file and from NV before vOSS has been started so that
3978 the final contents are available to send down to the cCPU */
3979
3980 // Apply the cfg.ini to cfg.dat
3981 if (FALSE == hdd_update_config_dat(pHddCtx))
3982 {
3983 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
3984 goto err_vosclose;
3985 }
3986
3987 // Apply the NV to cfg.dat
3988 /* Prima Update MAC address only at here */
3989 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
3990 {
3991#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
3992 /* There was not a valid set of MAC Addresses in NV. See if the
3993 default addresses were modified by the cfg.ini settings. If so,
3994 we'll use them, but if not, we'll autogenerate a set of MAC
3995 addresses based upon the device serial number */
3996
3997 static const v_MACADDR_t default_address =
3998 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
3999 unsigned int serialno;
4000 int i;
4001
4002 serialno = wcnss_get_serial_number();
4003 if ((0 != serialno) &&
4004 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
4005 sizeof(default_address))))
4006 {
4007 /* cfg.ini has the default address, invoke autogen logic */
4008
4009 /* MAC address has 3 bytes of OUI so we have a maximum of 3
4010 bytes of the serial number that can be used to generate
4011 the other 3 bytes of the MAC address. Mask off all but
4012 the lower 3 bytes (this will also make sure we don't
4013 overflow in the next step) */
4014 serialno &= 0x00FFFFFF;
4015
4016 /* we need a unique address for each session */
4017 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
4018
4019 /* autogen all addresses */
4020 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4021 {
4022 /* start with the entire default address */
4023 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
4024 /* then replace the lower 3 bytes */
4025 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
4026 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
4027 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
4028
4029 serialno++;
4030 }
4031
4032 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
4033 MAC_ADDRESS_STR,
4034 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4035 }
4036 else
4037#endif //WLAN_AUTOGEN_MACADDR_FEATURE
4038 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004039 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004040 "%s: Invalid MAC address in NV, using MAC from ini file "
4041 MAC_ADDRESS_STR, __func__,
4042 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4043 }
4044 }
4045 {
4046 eHalStatus halStatus;
4047 // Set the MAC Address
4048 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
4049 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
4050 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
4051 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
4052
4053 if (!HAL_STATUS_SUCCESS( halStatus ))
4054 {
4055 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
4056 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08004057 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004058 }
4059 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004060
4061 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
4062 Note: Firmware image will be read and downloaded inside vos_start API */
4063 status = vos_start( pHddCtx->pvosContext );
4064 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4065 {
4066 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
4067 goto err_vosclose;
4068 }
4069
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004070 /* Exchange capability info between Host and FW and also get versioning info from FW */
4071 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004072
4073 status = hdd_post_voss_start_config( pHddCtx );
4074 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4075 {
4076 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
4077 __func__);
4078 goto err_vosstop;
4079 }
4080
Jeff Johnson295189b2012-06-20 16:38:30 -07004081 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4082 {
4083 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
4084 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4085 }
4086 else
4087 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004088 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
4089 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4090 if (pAdapter != NULL)
4091 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304092 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07004093 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304094 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
4095 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
4096 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07004097
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304098 /* Generate the P2P Device Address. This consists of the device's
4099 * primary MAC address with the locally administered bit set.
4100 */
4101 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07004102 }
4103 else
4104 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304105 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
4106 if (p2p_dev_addr != NULL)
4107 {
4108 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
4109 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
4110 }
4111 else
4112 {
4113 hddLog(VOS_TRACE_LEVEL_FATAL,
4114 "%s: Failed to allocate mac_address for p2p_device",
4115 __func__);
4116 goto err_close_adapter;
4117 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004118 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004119
4120 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
4121 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
4122 if ( NULL == pP2pAdapter )
4123 {
4124 hddLog(VOS_TRACE_LEVEL_FATAL,
4125 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004126 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004127 goto err_close_adapter;
4128 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004129 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004130 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004131
4132 if( pAdapter == NULL )
4133 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004134 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
4135 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004136 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004137
Jeff Johnson295189b2012-06-20 16:38:30 -07004138#ifdef WLAN_BTAMP_FEATURE
4139 vStatus = WLANBAP_Open(pVosContext);
4140 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4141 {
4142 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4143 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004144 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004145 }
4146
4147 vStatus = BSL_Init(pVosContext);
4148 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4149 {
4150 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4151 "%s: Failed to Init BSL",__func__);
4152 goto err_bap_close;
4153 }
4154 vStatus = WLANBAP_Start(pVosContext);
4155 if (!VOS_IS_STATUS_SUCCESS(vStatus))
4156 {
4157 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4158 "%s: Failed to start TL",__func__);
4159 goto err_bap_close;
4160 }
4161
4162 pConfig = pHddCtx->cfg_ini;
4163 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
4164 status = WLANBAP_SetConfig(&btAmpConfig);
4165
4166#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07004167
Jeff Johnson295189b2012-06-20 16:38:30 -07004168#ifdef FEATURE_WLAN_SCAN_PNO
4169 /*SME must send channel update configuration to RIVA*/
4170 sme_UpdateChannelConfig(pHddCtx->hHal);
4171#endif
4172
Jeff Johnson295189b2012-06-20 16:38:30 -07004173 /* Register with platform driver as client for Suspend/Resume */
4174 status = hddRegisterPmOps(pHddCtx);
4175 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4176 {
4177 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
4178#ifdef WLAN_BTAMP_FEATURE
4179 goto err_bap_stop;
4180#else
Jeff Johnsone7245742012-09-05 17:12:55 -07004181 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004182#endif //WLAN_BTAMP_FEATURE
4183 }
4184
4185 /* Register TM level change handler function to the platform */
4186 status = hddDevTmRegisterNotifyCallback(pHddCtx);
4187 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4188 {
4189 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
4190 goto err_unregister_pmops;
4191 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004192
4193 /* register for riva power on lock to platform driver */
4194 if (req_riva_power_on_lock("wlan"))
4195 {
4196 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
4197 __func__);
4198 goto err_unregister_pmops;
4199 }
4200
Jeff Johnson295189b2012-06-20 16:38:30 -07004201 // register net device notifier for device change notification
4202 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4203
4204 if(ret < 0)
4205 {
4206 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
4207 goto err_free_power_on_lock;
4208 }
4209
4210 //Initialize the nlink service
4211 if(nl_srv_init() != 0)
4212 {
4213 hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
4214 goto err_reg_netdev;
4215 }
4216
4217 //Initialize the BTC service
4218 if(btc_activate_service(pHddCtx) != 0)
4219 {
4220 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
4221 goto err_nl_srv;
4222 }
4223
4224#ifdef PTT_SOCK_SVC_ENABLE
4225 //Initialize the PTT service
4226 if(ptt_sock_activate_svc(pHddCtx) != 0)
4227 {
4228 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
4229 goto err_nl_srv;
4230 }
4231#endif
4232
Jeff Johnson295189b2012-06-20 16:38:30 -07004233 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004234 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004235 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07004236 /* Action frame registered in one adapter which will
4237 * applicable to all interfaces
4238 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07004239 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07004240 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004241
4242 mutex_init(&pHddCtx->sap_lock);
4243
4244 pHddCtx->isLoadUnloadInProgress = FALSE;
4245
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004246#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004247#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4248 /* Initialize the wake lcok */
4249 wake_lock_init(&pHddCtx->rx_wake_lock,
4250 WAKE_LOCK_SUSPEND,
4251 "qcom_rx_wakelock");
4252#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004253 /* Initialize the wake lcok */
4254 wake_lock_init(&pHddCtx->sap_wake_lock,
4255 WAKE_LOCK_SUSPEND,
4256 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004257#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004258
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004259 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
4260 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07004261
4262 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4263 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004264
4265 // Initialize the restart logic
4266 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05304267
Jeff Johnson295189b2012-06-20 16:38:30 -07004268 goto success;
4269
4270err_nl_srv:
4271 nl_srv_exit();
4272
4273err_reg_netdev:
4274 unregister_netdevice_notifier(&hdd_netdev_notifier);
4275
4276err_free_power_on_lock:
4277 free_riva_power_on_lock("wlan");
4278
4279err_unregister_pmops:
4280 hddDevTmUnregisterNotifyCallback(pHddCtx);
4281 hddDeregisterPmOps(pHddCtx);
4282
4283#ifdef WLAN_BTAMP_FEATURE
4284err_bap_stop:
4285 WLANBAP_Stop(pVosContext);
4286#endif
4287
4288#ifdef WLAN_BTAMP_FEATURE
4289err_bap_close:
4290 WLANBAP_Close(pVosContext);
4291#endif
4292
Jeff Johnson295189b2012-06-20 16:38:30 -07004293err_close_adapter:
4294 hdd_close_all_adapters( pHddCtx );
4295
4296err_vosstop:
4297 vos_stop(pVosContext);
4298
4299err_vosclose:
4300 status = vos_sched_close( pVosContext );
4301 if (!VOS_IS_STATUS_SUCCESS(status)) {
4302 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4303 "%s: Failed to close VOSS Scheduler", __func__);
4304 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
4305 }
4306 vos_close(pVosContext );
4307
Jeff Johnson295189b2012-06-20 16:38:30 -07004308err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004309 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004310
4311err_wdclose:
4312 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4313 vos_watchdog_close(pVosContext);
4314
Jeff Johnson295189b2012-06-20 16:38:30 -07004315err_wiphy_reg:
4316 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004317
4318err_config:
4319 kfree(pHddCtx->cfg_ini);
4320 pHddCtx->cfg_ini= NULL;
4321
4322err_free_hdd_context:
4323 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004324 wiphy_free(wiphy) ;
4325 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004326 VOS_BUG(1);
4327
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08004328 if (hdd_is_ssr_required())
4329 {
4330 /* WDI timeout had happened during load, so SSR is needed here */
4331 subsystem_restart("wcnss");
4332 msleep(5000);
4333 }
4334 hdd_set_ssr_required (VOS_FALSE);
4335
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004336 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004337
4338success:
4339 EXIT();
4340 return 0;
4341}
4342
4343/**---------------------------------------------------------------------------
4344
Jeff Johnson32d95a32012-09-10 13:15:23 -07004345 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07004346
Jeff Johnson32d95a32012-09-10 13:15:23 -07004347 This is the driver entry point - called in different timeline depending
4348 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07004349
4350 \param - None
4351
4352 \return - 0 for success, non zero for failure
4353
4354 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07004355static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004356{
4357 VOS_STATUS status;
4358 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004359 struct device *dev = NULL;
4360 int ret_status = 0;
4361
4362 ENTER();
4363
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004364#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004365 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07004366#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004367
4368 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
4369 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
4370
4371 //Power Up Libra WLAN card first if not already powered up
4372 status = vos_chipPowerUp(NULL,NULL,NULL);
4373 if (!VOS_IS_STATUS_SUCCESS(status))
4374 {
4375 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
4376 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004377 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004378 }
4379
Jeff Johnson295189b2012-06-20 16:38:30 -07004380#ifdef ANI_BUS_TYPE_PCI
4381
4382 dev = wcnss_wlan_get_device();
4383
4384#endif // ANI_BUS_TYPE_PCI
4385
4386#ifdef ANI_BUS_TYPE_PLATFORM
4387 dev = wcnss_wlan_get_device();
4388#endif // ANI_BUS_TYPE_PLATFORM
4389
4390
4391 do {
4392 if (NULL == dev) {
4393 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
4394 ret_status = -1;
4395 break;
4396 }
4397
4398#ifdef MEMORY_DEBUG
4399 vos_mem_init();
4400#endif
4401
4402#ifdef TIMER_MANAGER
4403 vos_timer_manager_init();
4404#endif
4405
4406 /* Preopen VOSS so that it is ready to start at least SAL */
4407 status = vos_preOpen(&pVosContext);
4408
4409 if (!VOS_IS_STATUS_SUCCESS(status))
4410 {
4411 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
4412 ret_status = -1;
4413 break;
4414 }
4415
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004416#ifndef MODULE
4417 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
4418 */
4419 hdd_set_conparam((v_UINT_t)con_mode);
4420#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004421
4422 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004423 if (hdd_wlan_startup(dev))
4424 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004425 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004426 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004427 vos_preClose( &pVosContext );
4428 ret_status = -1;
4429 break;
4430 }
4431
4432 /* Cancel the vote for XO Core ON
4433 * This is done here for safety purposes in case we re-initialize without turning
4434 * it OFF in any error scenario.
4435 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004436 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07004437 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004438 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07004439 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4440 {
4441 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
4442 " Power consumed will be high\n");
4443 }
4444 } while (0);
4445
4446 if (0 != ret_status)
4447 {
4448 //Assert Deep sleep signal now to put Libra HW in lowest power state
4449 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4450 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
4451
4452 //Vote off any PMIC voltage supplies
4453 vos_chipPowerDown(NULL, NULL, NULL);
4454#ifdef TIMER_MANAGER
4455 vos_timer_exit();
4456#endif
4457#ifdef MEMORY_DEBUG
4458 vos_mem_exit();
4459#endif
4460
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004461#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004462 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004463#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004464 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
4465 }
4466 else
4467 {
4468 //Send WLAN UP indication to Nlink Service
4469 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
4470
4471 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
4472
4473 }
4474
4475 EXIT();
4476
4477 return ret_status;
4478}
4479
Jeff Johnson32d95a32012-09-10 13:15:23 -07004480/**---------------------------------------------------------------------------
4481
4482 \brief hdd_module_init() - Init Function
4483
4484 This is the driver entry point (invoked when module is loaded using insmod)
4485
4486 \param - None
4487
4488 \return - 0 for success, non zero for failure
4489
4490 --------------------------------------------------------------------------*/
4491#ifdef MODULE
4492static int __init hdd_module_init ( void)
4493{
4494 return hdd_driver_init();
4495}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004496#else /* #ifdef MODULE */
4497static int __init hdd_module_init ( void)
4498{
4499 /* Driver initialization is delayed to fwpath_changed_handler */
4500 return 0;
4501}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004502#endif /* #ifdef MODULE */
4503
Jeff Johnson295189b2012-06-20 16:38:30 -07004504
4505/**---------------------------------------------------------------------------
4506
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004507 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07004508
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004509 This is the driver exit point (invoked when module is unloaded using rmmod
4510 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07004511
4512 \param - None
4513
4514 \return - None
4515
4516 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004517static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004518{
4519 hdd_context_t *pHddCtx = NULL;
4520 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004521
4522 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
4523
4524 //Get the global vos context
4525 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4526
4527 if(!pVosContext)
4528 {
4529 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
4530 goto done;
4531 }
4532
4533 //Get the HDD context.
4534 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
4535
4536 if(!pHddCtx)
4537 {
4538 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
4539 }
4540 else
4541 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004542 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07004543 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07004544 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
4545 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07004546 }
4547
4548 pHddCtx->isLoadUnloadInProgress = TRUE;
4549 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4550
4551 //Do all the cleanup before deregistering the driver
4552 hdd_wlan_exit(pHddCtx);
4553 }
4554
Jeff Johnson295189b2012-06-20 16:38:30 -07004555 vos_preClose( &pVosContext );
4556
4557#ifdef TIMER_MANAGER
4558 vos_timer_exit();
4559#endif
4560#ifdef MEMORY_DEBUG
4561 vos_mem_exit();
4562#endif
4563
4564done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004565#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004566 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004567#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004568 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
4569}
4570
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004571/**---------------------------------------------------------------------------
4572
4573 \brief hdd_module_exit() - Exit function
4574
4575 This is the driver exit point (invoked when module is unloaded using rmmod)
4576
4577 \param - None
4578
4579 \return - None
4580
4581 --------------------------------------------------------------------------*/
4582static void __exit hdd_module_exit(void)
4583{
4584 hdd_driver_exit();
4585}
4586
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004587#ifdef MODULE
4588static int fwpath_changed_handler(const char *kmessage,
4589 struct kernel_param *kp)
4590{
4591 /* nothing to do when driver is DLKM */
4592 return 0;
4593}
4594
4595static int con_mode_handler(const char *kmessage,
4596 struct kernel_param *kp)
4597{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07004598 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004599}
4600#else /* #ifdef MODULE */
4601/**---------------------------------------------------------------------------
4602
4603 \brief fwpath_changed_handler() - Handler Function
4604
4605 This is the driver entry point
4606 - delayed driver initialization when driver is statically linked
4607 - invoked when module parameter fwpath is modified from userpspace to signal
4608 initializing the WLAN driver
4609
4610 \return - 0 for success, non zero for failure
4611
4612 --------------------------------------------------------------------------*/
4613static int fwpath_changed_handler(const char *kmessage,
4614 struct kernel_param *kp)
4615{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004616 int ret_status;
4617
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004618 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004619 ret_status = hdd_driver_init();
4620 wlan_hdd_inited = ret_status ? 0 : 1;
4621 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004622 }
4623
4624 hdd_driver_exit();
4625
4626 msleep(200);
4627
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004628 ret_status = hdd_driver_init();
4629 wlan_hdd_inited = ret_status ? 0 : 1;
4630 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004631}
4632
Jeff Johnson295189b2012-06-20 16:38:30 -07004633/**---------------------------------------------------------------------------
4634
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004635 \brief con_mode_handler() -
4636
4637 Handler function for module param con_mode when it is changed by userspace
4638 Dynamically linked - do nothing
4639 Statically linked - exit and init driver, as in rmmod and insmod
4640
4641 \param -
4642
4643 \return -
4644
4645 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004646static int con_mode_handler(const char *kmessage,
4647 struct kernel_param *kp)
4648{
4649 int ret = param_set_int(kmessage, kp);
4650
4651 if (ret)
4652 return ret;
4653
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004654 return fwpath_changed_handler(kmessage, kp);
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004655}
4656#endif /* #ifdef MODULE */
4657
4658/**---------------------------------------------------------------------------
4659
Jeff Johnson295189b2012-06-20 16:38:30 -07004660 \brief hdd_get_conparam() -
4661
4662 This is the driver exit point (invoked when module is unloaded using rmmod)
4663
4664 \param - None
4665
4666 \return - tVOS_CON_MODE
4667
4668 --------------------------------------------------------------------------*/
4669tVOS_CON_MODE hdd_get_conparam ( void )
4670{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004671#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07004672 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004673#else
4674 return (tVOS_CON_MODE)curr_con_mode;
4675#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004676}
4677void hdd_set_conparam ( v_UINT_t newParam )
4678{
4679 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004680#ifndef MODULE
4681 curr_con_mode = con_mode;
4682#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004683}
4684/**---------------------------------------------------------------------------
4685
4686 \brief hdd_softap_sta_deauth() - function
4687
4688 This to take counter measure to handle deauth req from HDD
4689
4690 \param - pAdapter - Pointer to the HDD
4691
4692 \param - enable - boolean value
4693
4694 \return - None
4695
4696 --------------------------------------------------------------------------*/
4697
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004698VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07004699{
Jeff Johnson295189b2012-06-20 16:38:30 -07004700 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004701 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07004702
4703 ENTER();
4704
4705 hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4706
4707 //Ignore request to deauth bcmc station
4708 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004709 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004710
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004711 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07004712
4713 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004714 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004715}
4716
4717/**---------------------------------------------------------------------------
4718
4719 \brief hdd_softap_sta_disassoc() - function
4720
4721 This to take counter measure to handle deauth req from HDD
4722
4723 \param - pAdapter - Pointer to the HDD
4724
4725 \param - enable - boolean value
4726
4727 \return - None
4728
4729 --------------------------------------------------------------------------*/
4730
4731void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
4732{
4733 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4734
4735 ENTER();
4736
4737 hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4738
4739 //Ignore request to disassoc bcmc station
4740 if( pDestMacAddress[0] & 0x1 )
4741 return;
4742
4743 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
4744}
4745
4746void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
4747{
4748 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4749
4750 ENTER();
4751
4752 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4753
4754 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
4755}
4756
Jeff Johnson295189b2012-06-20 16:38:30 -07004757/**---------------------------------------------------------------------------
4758 *
4759 * \brief hdd_get__concurrency_mode() -
4760 *
4761 *
4762 * \param - None
4763 *
4764 * \return - CONCURRENCY MODE
4765 *
4766 * --------------------------------------------------------------------------*/
4767tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
4768{
4769 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
4770 hdd_context_t *pHddCtx;
4771
4772 if (NULL != pVosContext)
4773 {
4774 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
4775 if (NULL != pHddCtx)
4776 {
4777 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
4778 }
4779 }
4780
4781 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004782 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004783 return VOS_STA;
4784}
4785
4786/* Decide whether to allow/not the apps power collapse.
4787 * Allow apps power collapse if we are in connected state.
4788 * if not, allow only if we are in IMPS */
4789v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
4790{
4791 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08004792 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08004793 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07004794 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4795 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4796 hdd_adapter_t *pAdapter = NULL;
4797 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08004798 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004799
Jeff Johnson295189b2012-06-20 16:38:30 -07004800 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4801 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004802
Yathish9f22e662012-12-10 14:21:35 -08004803 concurrent_state = hdd_get_concurrency_mode();
4804
4805#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4806 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
4807 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
4808 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
4809 return TRUE;
4810#endif
4811
Jeff Johnson295189b2012-06-20 16:38:30 -07004812 /*loop through all adapters. TBD fix for Concurrency */
4813 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4814 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4815 {
4816 pAdapter = pAdapterNode->pAdapter;
4817 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4818 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4819 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08004820 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07004821 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08004822 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08004823 (eANI_BOOLEAN_TRUE == scanRspPending) ||
4824 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07004825 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08004826 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08004827 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
4828 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07004829 return FALSE;
4830 }
4831 }
4832 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4833 pAdapterNode = pNext;
4834 }
4835 return TRUE;
4836}
4837
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08004838/* Decides whether to send suspend notification to Riva
4839 * if any adapter is in BMPS; then it is required */
4840v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
4841{
4842 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
4843 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4844
4845 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
4846 {
4847 return TRUE;
4848 }
4849 return FALSE;
4850}
4851
Jeff Johnson295189b2012-06-20 16:38:30 -07004852void wlan_hdd_set_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:
Jeff Johnsone7245742012-09-05 17:12:55 -07004860 pHddCtx->concurrency_mode |= (1 << mode);
4861 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07004862 break;
4863 default:
4864 break;
4865
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
4871
4872void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
4873{
4874 switch(mode)
4875 {
4876 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07004877 case WLAN_HDD_P2P_CLIENT:
4878 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004879 case WLAN_HDD_SOFTAP:
4880 pHddCtx->no_of_sessions[mode]--;
4881 if (!(pHddCtx->no_of_sessions[mode]))
4882 pHddCtx->concurrency_mode &= (~(1 << mode));
4883 break;
4884 default:
4885 break;
4886 }
4887 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
4888 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
4889}
4890
Jeff Johnsone7245742012-09-05 17:12:55 -07004891/**---------------------------------------------------------------------------
4892 *
4893 * \brief wlan_hdd_restart_init
4894 *
4895 * This function initalizes restart timer/flag. An internal function.
4896 *
4897 * \param - pHddCtx
4898 *
4899 * \return - None
4900 *
4901 * --------------------------------------------------------------------------*/
4902
4903static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
4904{
4905 /* Initialize */
4906 pHddCtx->hdd_restart_retries = 0;
4907 atomic_set(&pHddCtx->isRestartInProgress, 0);
4908 vos_timer_init(&pHddCtx->hdd_restart_timer,
4909 VOS_TIMER_TYPE_SW,
4910 wlan_hdd_restart_timer_cb,
4911 pHddCtx);
4912}
4913/**---------------------------------------------------------------------------
4914 *
4915 * \brief wlan_hdd_restart_deinit
4916 *
4917 * This function cleans up the resources used. An internal function.
4918 *
4919 * \param - pHddCtx
4920 *
4921 * \return - None
4922 *
4923 * --------------------------------------------------------------------------*/
4924
4925static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
4926{
4927
4928 VOS_STATUS vos_status;
4929 /* Block any further calls */
4930 atomic_set(&pHddCtx->isRestartInProgress, 1);
4931 /* Cleanup */
4932 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
4933 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004934 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07004935 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
4936 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004937 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07004938
4939}
4940
4941/**---------------------------------------------------------------------------
4942 *
4943 * \brief wlan_hdd_framework_restart
4944 *
4945 * This function uses a cfg80211 API to start a framework initiated WLAN
4946 * driver module unload/load.
4947 *
4948 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
4949 *
4950 *
4951 * \param - pHddCtx
4952 *
4953 * \return - VOS_STATUS_SUCCESS: Success
4954 * VOS_STATUS_E_EMPTY: Adapter is Empty
4955 * VOS_STATUS_E_NOMEM: No memory
4956
4957 * --------------------------------------------------------------------------*/
4958
4959static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
4960{
4961 VOS_STATUS status = VOS_STATUS_SUCCESS;
4962 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4963 int len = (sizeof (struct ieee80211_mgmt));
4964 struct ieee80211_mgmt *mgmt = NULL;
4965
4966 /* Prepare the DEAUTH managment frame with reason code */
4967 mgmt = kzalloc(len, GFP_KERNEL);
4968 if(mgmt == NULL)
4969 {
4970 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1250df42012-12-10 14:31:52 -08004971 "%s: memory allocation failed (%d bytes)", __func__, len);
Jeff Johnsone7245742012-09-05 17:12:55 -07004972 return VOS_STATUS_E_NOMEM;
4973 }
4974 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
4975
4976 /* Iterate over all adapters/devices */
4977 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4978 do
4979 {
4980 if( (status == VOS_STATUS_SUCCESS) &&
4981 pAdapterNode &&
4982 pAdapterNode->pAdapter)
4983 {
4984 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4985 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
4986 pAdapterNode->pAdapter->dev->name,
4987 pAdapterNode->pAdapter->device_mode,
4988 pHddCtx->hdd_restart_retries + 1);
4989 /*
4990 * CFG80211 event to restart the driver
4991 *
4992 * 'cfg80211_send_unprot_deauth' sends a
4993 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
4994 * of SME(Linux Kernel) state machine.
4995 *
4996 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
4997 * the driver.
4998 *
4999 */
5000
5001 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
5002 }
5003 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5004 pAdapterNode = pNext;
5005 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
5006
5007
5008 /* Free the allocated management frame */
5009 kfree(mgmt);
5010
5011 /* Retry until we unload or reach max count */
5012 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
5013 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
5014
5015 return status;
5016
5017}
5018/**---------------------------------------------------------------------------
5019 *
5020 * \brief wlan_hdd_restart_timer_cb
5021 *
5022 * Restart timer callback. An internal function.
5023 *
5024 * \param - User data:
5025 *
5026 * \return - None
5027 *
5028 * --------------------------------------------------------------------------*/
5029
5030void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
5031{
5032 hdd_context_t *pHddCtx = usrDataForCallback;
5033 wlan_hdd_framework_restart(pHddCtx);
5034 return;
5035
5036}
5037
5038
5039/**---------------------------------------------------------------------------
5040 *
5041 * \brief wlan_hdd_restart_driver
5042 *
5043 * This function sends an event to supplicant to restart the WLAN driver.
5044 *
5045 * This function is called from vos_wlanRestart.
5046 *
5047 * \param - pHddCtx
5048 *
5049 * \return - VOS_STATUS_SUCCESS: Success
5050 * VOS_STATUS_E_EMPTY: Adapter is Empty
5051 * VOS_STATUS_E_ALREADY: Request already in progress
5052
5053 * --------------------------------------------------------------------------*/
5054VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
5055{
5056 VOS_STATUS status = VOS_STATUS_SUCCESS;
5057
5058 /* A tight check to make sure reentrancy */
5059 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
5060 {
5061 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
5062 "%s: WLAN restart is already in progress", __func__);
5063
5064 return VOS_STATUS_E_ALREADY;
5065 }
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005066 /* when WLAN driver is statically linked, then invoke SSR by sending
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005067 * the reset interrupt. If it is DLKM, then use restart API
5068 */
5069#ifdef MODULE
Jeff Johnsone7245742012-09-05 17:12:55 -07005070 status = wlan_hdd_framework_restart(pHddCtx);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005071#else
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005072#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005073 wcnss_reset_intr();
5074#endif
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005075#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005076
Jeff Johnsone7245742012-09-05 17:12:55 -07005077 return status;
5078}
5079
5080
Jeff Johnson295189b2012-06-20 16:38:30 -07005081//Register the module init/exit functions
5082module_init(hdd_module_init);
5083module_exit(hdd_module_exit);
5084
5085MODULE_LICENSE("Dual BSD/GPL");
5086MODULE_AUTHOR("Qualcomm Atheros, Inc.");
5087MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
5088
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005089module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
5090 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07005091
5092module_param_call(fwpath, fwpath_changed_handler, param_get_string, fwpath,
5093 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);