blob: 0bdbcf331b103c13f71ed4d4db9eda560f5e7b98 [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);
Jeff Johnson27cee452013-03-27 11:10:24 -0700193 hdd_context_t *pHddCtx;
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.
Jeff Johnson27cee452013-03-27 11:10:24 -0700200 if ((strncmp(dev->name, "wlan", 4)) &&
201 (strncmp(dev->name, "p2p", 3)))
Jeff Johnson295189b2012-06-20 16:38:30 -0700202 return NOTIFY_DONE;
203
Jeff Johnson295189b2012-06-20 16:38:30 -0700204 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700205 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700206
Jeff Johnson27cee452013-03-27 11:10:24 -0700207 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700208 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800209 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700210 VOS_ASSERT(0);
211 return NOTIFY_DONE;
212 }
213
Jeff Johnson27cee452013-03-27 11:10:24 -0700214 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
215 if (NULL == pHddCtx)
216 {
217 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
218 VOS_ASSERT(0);
219 return NOTIFY_DONE;
220 }
221
222 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
223 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700224
225 switch (state) {
226 case NETDEV_REGISTER:
227 break;
228
229 case NETDEV_UNREGISTER:
230 break;
231
232 case NETDEV_UP:
233 break;
234
235 case NETDEV_DOWN:
236 break;
237
238 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700239 if(TRUE == pAdapter->isLinkUpSvcNeeded)
240 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700241 break;
242
243 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700244 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700245 {
246 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800247 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700248 hdd_abort_mac_scan(pAdapter->pHddCtx);
249 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800250 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700251 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
252 if(!result)
253 {
254 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800255 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700256 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700257 }
258 }
259 else
260 {
261 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700262 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700263 }
264#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700265 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700266 status = WLANBAP_StopAmp();
267 if(VOS_STATUS_SUCCESS != status )
268 {
269 pHddCtx->isAmpAllowed = VOS_TRUE;
270 hddLog(VOS_TRACE_LEVEL_FATAL,
271 "%s: Failed to stop AMP", __func__);
272 }
273 else
274 {
275 //a state m/c implementation in PAL is TBD to avoid this delay
276 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700277 if ( pHddCtx->isAmpAllowed )
278 {
279 WLANBAP_DeregisterFromHCI();
280 pHddCtx->isAmpAllowed = VOS_FALSE;
281 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700282 }
283#endif //WLAN_BTAMP_FEATURE
284 break;
285
286 default:
287 break;
288 }
289
290 return NOTIFY_DONE;
291}
292
293struct notifier_block hdd_netdev_notifier = {
294 .notifier_call = hdd_netdev_notifier_call,
295};
296
297/*---------------------------------------------------------------------------
298 * Function definitions
299 *-------------------------------------------------------------------------*/
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800300int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700301void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
302void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700303//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700304static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700305#ifndef MODULE
306/* current con_mode - used only for statically linked driver
307 * con_mode is changed by userspace to indicate a mode change which will
308 * result in calling the module exit and init functions. The module
309 * exit function will clean up based on the value of con_mode prior to it
310 * being changed by userspace. So curr_con_mode records the current con_mode
311 * for exit when con_mode becomes the next mode for init
312 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700313static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700314#endif
315
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800316/**---------------------------------------------------------------------------
317
318 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
319
320 Called immediately after the cfg.ini is read in order to configure
321 the desired trace levels.
322
323 \param - moduleId - module whose trace level is being configured
324 \param - bitmask - bitmask of log levels to be enabled
325
326 \return - void
327
328 --------------------------------------------------------------------------*/
329static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
330{
331 wpt_tracelevel level;
332
333 /* if the bitmask is the default value, then a bitmask was not
334 specified in cfg.ini, so leave the logging level alone (it
335 will remain at the "compiled in" default value) */
336 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
337 {
338 return;
339 }
340
341 /* a mask was specified. start by disabling all logging */
342 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
343
344 /* now cycle through the bitmask until all "set" bits are serviced */
345 level = VOS_TRACE_LEVEL_FATAL;
346 while (0 != bitmask)
347 {
348 if (bitmask & 1)
349 {
350 vos_trace_setValue(moduleId, level, 1);
351 }
352 level++;
353 bitmask >>= 1;
354 }
355}
356
357
Jeff Johnson295189b2012-06-20 16:38:30 -0700358/**---------------------------------------------------------------------------
359
360 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
361
362 Called immediately after the cfg.ini is read in order to configure
363 the desired trace levels in the WDI.
364
365 \param - moduleId - module whose trace level is being configured
366 \param - bitmask - bitmask of log levels to be enabled
367
368 \return - void
369
370 --------------------------------------------------------------------------*/
371static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
372{
373 wpt_tracelevel level;
374
375 /* if the bitmask is the default value, then a bitmask was not
376 specified in cfg.ini, so leave the logging level alone (it
377 will remain at the "compiled in" default value) */
378 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
379 {
380 return;
381 }
382
383 /* a mask was specified. start by disabling all logging */
384 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
385
386 /* now cycle through the bitmask until all "set" bits are serviced */
387 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
388 while (0 != bitmask)
389 {
390 if (bitmask & 1)
391 {
392 wpalTraceSetLevel(moduleId, level, 1);
393 }
394 level++;
395 bitmask >>= 1;
396 }
397}
Jeff Johnson295189b2012-06-20 16:38:30 -0700398
399int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
400{
401 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
402 hdd_priv_data_t priv_data;
403 tANI_U8 *command = NULL;
404 int ret = 0;
405
406 if (NULL == pAdapter)
407 {
408 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700409 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700410 ret = -ENODEV;
411 goto exit;
412 }
413
Jeff Johnsone7245742012-09-05 17:12:55 -0700414 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700415 {
416 ret = -EINVAL;
417 goto exit;
418 }
419
420 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
421 {
422 ret = -EFAULT;
423 goto exit;
424 }
425
426 command = kmalloc(priv_data.total_len, GFP_KERNEL);
427 if (!command)
428 {
429 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700430 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700431 ret = -ENOMEM;
432 goto exit;
433 }
434
435 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
436 {
437 ret = -EFAULT;
438 goto exit;
439 }
440
441 if ((SIOCDEVPRIVATE + 1) == cmd)
442 {
443 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
444
445 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700446 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700447
448 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
449 {
450 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
451 sizeof(tSirMacAddr)))
452 {
453 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700454 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700455 ret = -EFAULT;
456 }
457 }
Amar Singhal0974e402013-02-12 14:27:46 -0800458 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700459 {
Amar Singhal0974e402013-02-12 14:27:46 -0800460 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700461 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800462
Jeff Johnson295189b2012-06-20 16:38:30 -0700463 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800464
465 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700466 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700467 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800468 "%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 -0700469 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800470 ret = hdd_setBand_helper(dev, ptr);
471 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700472 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
473 {
474 char *country_code;
475
476 country_code = command + 8;
477 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
478 pAdapter, pHddCtx->pvosContext);
479 if( 0 != ret )
480 {
481 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
482 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
483
484 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700485 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800486#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
487 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
488 {
489 tANI_U8 *value = command;
490 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
491 tANI_U8 revision = 0;
492 eHalStatus status = eHAL_STATUS_SUCCESS;
493 v_REGDOMAIN_t regId;
494
495 status = hdd_parse_countryrev(value, countryCode, &revision);
496 if (eHAL_STATUS_SUCCESS != status)
497 {
498 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
499 "%s: Failed to parse country revision information", __func__);
500 ret = -EINVAL;
501 goto exit;
502 }
503
504 /* Validate country code */
505 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
506 if (eHAL_STATUS_SUCCESS != status)
507 {
508 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
509 "%s: Invalid country code %s", __func__, countryCode);
510 ret = -EINVAL;
511 goto exit;
512 }
513
514 /* Validate revision */
515 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
516 {
517 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
518 "%s: Invalid revision %d", __func__, revision);
519 ret = -EINVAL;
520 goto exit;
521 }
522
523 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
524 pAdapter, pHddCtx->pvosContext);
525 if (0 != ret)
526 {
527 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
528 "%s: SME Change Country code fail ret=%d", __func__, ret);
529 ret = -EINVAL;
530 goto exit;
531 }
532
533 if (0 == strncmp(countryCode, "KR", 2))
534 {
535 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
536 revision);
537 if (eHAL_STATUS_SUCCESS != status)
538 {
539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
540 "%s: Failed to build valid channel list", __func__);
541 ret = -EINVAL;
542 goto exit;
543 }
544 }
545 }
546#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700547 /*
548 command should be a string having format
549 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
550 */
Amar Singhal0974e402013-02-12 14:27:46 -0800551 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700552 {
Amar Singhal0974e402013-02-12 14:27:46 -0800553 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700554
555 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700556 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700557
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800558 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700559 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800560 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
561 {
562 int suspend = 0;
563 tANI_U8 *ptr = (tANI_U8*)command + 15;
564
565 suspend = *ptr - '0';
566 hdd_set_wlan_suspend_mode(suspend);
567 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800568#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
569 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
570 {
571 tANI_U8 *value = command;
572 int rssi = 0;
573 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
574 eHalStatus status = eHAL_STATUS_SUCCESS;
575
576 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
577 value = value + 15;
578
579 sscanf(value, "%d", &rssi);
580 lookUpThreshold = abs(rssi);
581 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
582 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
583 {
584 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
585 "Neighbor lookup threshold value %d is out of range"
586 " (Min: %d Max: %d)", lookUpThreshold,
587 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
588 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
589 ret = -EINVAL;
590 goto exit;
591 }
592
593 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
594 "%s: Received Command to Set Roam trigger"
595 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
596
597 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
598 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
599 if (eHAL_STATUS_SUCCESS != status)
600 {
601 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
602 "%s: Failed to set roam trigger, try again", __func__);
603 ret = -EPERM;
604 goto exit;
605 }
606
607 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
608 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
609 }
610 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
611 {
612 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
613 int rssi = (-1) * lookUpThreshold;
614 char extra[32];
615 tANI_U8 len = 0;
616
617 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
618 if (copy_to_user(priv_data.buf, &extra, len + 1))
619 {
620 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
621 "%s: failed to copy data to user buffer", __func__);
622 ret = -EFAULT;
623 goto exit;
624 }
625 }
626 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
627 {
628 tANI_U8 *value = command;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700629 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800630 /* input refresh period is in terms of seconds */
631 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
632 value = value + 18;
633 /* Convert the value from ascii to integer */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700634 ret = kstrtou16(value, 10, &neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800635 if (ret < 0)
636 {
637 /* If the input value is greater than max value of datatype, then also
638 kstrtou16 fails */
639 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
640 "%s: kstrtou16 failed ",
641 "Input value may be out of range[%d - %d]",
642 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700643 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
644 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800645 ret = -EINVAL;
646 goto exit;
647 }
648
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700649 neighborEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod * 1000;
650 if ((neighborEmptyScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
651 (neighborEmptyScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800652 {
653 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700654 "Neighbor empty scan results refresh period value %d is out of range"
655 " (Min: %d Max: %d)", neighborEmptyScanRefreshPeriod/1000,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700656 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
657 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800658 ret = -EINVAL;
659 goto exit;
660 }
661
662 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
663 "%s: Received Command to Set roam scan period"
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700664 " (Empty Scan refresh period) = %d", __func__, neighborEmptyScanRefreshPeriod/1000);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800665
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700666 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
667 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800668 }
669 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
670 {
671 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
672 char extra[32];
673 tANI_U8 len = 0;
674
675 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
676 /* Returned value is in units of seconds */
677 if (copy_to_user(priv_data.buf, &extra, len + 1))
678 {
679 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
680 "%s: failed to copy data to user buffer", __func__);
681 ret = -EFAULT;
682 goto exit;
683 }
684 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700685 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
686 {
687 tANI_U8 *value = command;
688 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
689 /* input refresh period is in terms of seconds */
690 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
691 value = value + 25;
692 /* Convert the value from ascii to integer */
693 ret = kstrtou16(value, 10, &neighborScanRefreshPeriod);
694 if (ret < 0)
695 {
696 /* If the input value is greater than max value of datatype, then also
697 kstrtou16 fails */
698 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
699 "%s: kstrtou16 failed ",
700 "Input value may be out of range[%d - %d]",
701 __func__,
702 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
703 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
704 ret = -EINVAL;
705 goto exit;
706 }
707
708 neighborScanRefreshPeriod = neighborScanRefreshPeriod * 1000;
709 if ((neighborScanRefreshPeriod < CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN) ||
710 (neighborScanRefreshPeriod > CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX))
711 {
712 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
713 "Neighbor scan results refresh period value %d is out of range"
714 " (Min: %d Max: %d)", neighborScanRefreshPeriod/1000,
715 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
716 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
717 ret = -EINVAL;
718 goto exit;
719 }
720
721 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
722 "%s: Received Command to Set roam scan refresh period"
723 " (Scan refresh period) = %d", __func__, neighborScanRefreshPeriod/1000);
724
725 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
726 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
727 }
728 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
729 {
730 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
731 char extra[32];
732 tANI_U8 len = 0;
733
734 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
735 /* Returned value is in units of seconds */
736 if (copy_to_user(priv_data.buf, &extra, len + 1))
737 {
738 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
739 "%s: failed to copy data to user buffer", __func__);
740 ret = -EFAULT;
741 goto exit;
742 }
743 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800744#endif
745#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
746 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
747 {
748 tANI_U8 *value = command;
749 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
750
751 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
752 value = value + 13;
753 /* Convert the value from ascii to integer */
754 ret = kstrtou8(value, 10, &roamRssiDiff);
755 if (ret < 0)
756 {
757 /* If the input value is greater than max value of datatype, then also
758 kstrtou8 fails */
759 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
760 "%s: kstrtou8 failed range [%d - %d]", __func__,
761 CFG_ROAM_RSSI_DIFF_MIN,
762 CFG_ROAM_RSSI_DIFF_MAX);
763 ret = -EINVAL;
764 goto exit;
765 }
766
767 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
768 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
769 {
770 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
771 "Roam rssi diff value %d is out of range"
772 " (Min: %d Max: %d)", roamRssiDiff,
773 CFG_ROAM_RSSI_DIFF_MIN,
774 CFG_ROAM_RSSI_DIFF_MAX);
775 ret = -EINVAL;
776 goto exit;
777 }
778
779 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
780 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
781
782 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
783 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
784 }
785 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
786 {
787 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
788 char extra[32];
789 tANI_U8 len = 0;
790
791 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
792 if (copy_to_user(priv_data.buf, &extra, len + 1))
793 {
794 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
795 "%s: failed to copy data to user buffer", __func__);
796 ret = -EFAULT;
797 goto exit;
798 }
799 }
800#endif
801#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
802 else if (strncmp(command, "GETBAND", 7) == 0)
803 {
804 int band = -1;
805 char extra[32];
806 tANI_U8 len = 0;
807 hdd_getBand_helper(pHddCtx, &band);
808
809 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
810 if (copy_to_user(priv_data.buf, &extra, len + 1))
811 {
812 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
813 "%s: failed to copy data to user buffer", __func__);
814 ret = -EFAULT;
815 goto exit;
816 }
817 }
818 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
819 {
820 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
821 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
822 tANI_U8 revision = 0;
823 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
824 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
825 char extra[32] = {0};
826 tANI_U8 len = 0;
827
828 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
829 {
830 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
831 "%s: failed to get country code", __func__);
832 ret = -EFAULT;
833 goto exit;
834 }
835 pBuf[uBufLen] = '\0';
836 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
837
838 if (0 == strncmp(pBuf, "KR", 2))
839 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
840 else
841 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
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 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
852 {
853 tANI_U8 *value = command;
854 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
855 tANI_U8 numChannels = 0;
856 eHalStatus status = eHAL_STATUS_SUCCESS;
857
858 status = hdd_parse_channellist(value, ChannelList, &numChannels);
859 if (eHAL_STATUS_SUCCESS != status)
860 {
861 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
862 "%s: Failed to parse channel list information", __func__);
863 ret = -EINVAL;
864 goto exit;
865 }
866
867 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
868 {
869 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
870 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
871 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
872 ret = -EINVAL;
873 goto exit;
874 }
875 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
876 numChannels);
877 if (eHAL_STATUS_SUCCESS != status)
878 {
879 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
880 "%s: Failed to update channel list information", __func__);
881 ret = -EINVAL;
882 goto exit;
883 }
884 }
885 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
886 {
887 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
888 tANI_U8 numChannels = 0;
889 tANI_U8 len = 0, j = 0;
890 char extra[128] = {0};
891
892 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
893 ChannelList, &numChannels ))
894 {
895 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
896 "%s: failed to get roam scan channel list", __func__);
897 ret = -EFAULT;
898 goto exit;
899 }
900 /* output channel list is of the format
901 [Number of roam scan channels][Channel1][Channel2]... */
902 /* copy the number of channels in the 0th index */
903 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
904 for (j = 0; (j < numChannels); j++)
905 {
906 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
907 }
908
909 if (copy_to_user(priv_data.buf, &extra, len + 1))
910 {
911 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
912 "%s: failed to copy data to user buffer", __func__);
913 ret = -EFAULT;
914 goto exit;
915 }
916 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700917 else if (strncmp(command, "GETCCXMODE", 10) == 0)
918 {
919 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
920 char extra[32];
921 tANI_U8 len = 0;
922
923 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
924 if (copy_to_user(priv_data.buf, &extra, len + 1))
925 {
926 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
927 "%s: failed to copy data to user buffer", __func__);
928 ret = -EFAULT;
929 goto exit;
930 }
931 }
932 else if (strncmp(command, "GETOKCMODE", 10) == 0)
933 {
934 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
935 char extra[32];
936 tANI_U8 len = 0;
937
938 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
939 if (copy_to_user(priv_data.buf, &extra, len + 1))
940 {
941 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
942 "%s: failed to copy data to user buffer", __func__);
943 ret = -EFAULT;
944 goto exit;
945 }
946 }
947 else if (strncmp(command, "GETFASTROAM", 10) == 0)
948 {
949 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
950 char extra[32];
951 tANI_U8 len = 0;
952
953 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
954 if (copy_to_user(priv_data.buf, &extra, len + 1))
955 {
956 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
957 "%s: failed to copy data to user buffer", __func__);
958 ret = -EFAULT;
959 goto exit;
960 }
961 }
962 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
963 {
964 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
965 char extra[32];
966 tANI_U8 len = 0;
967
968 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
969 if (copy_to_user(priv_data.buf, &extra, len + 1))
970 {
971 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
972 "%s: failed to copy data to user buffer", __func__);
973 ret = -EFAULT;
974 goto exit;
975 }
976 }
977 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
978 {
979 tANI_U8 *value = command;
980 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
981
982 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
983 value = value + 26;
984 /* Convert the value from ascii to integer */
985 ret = kstrtou8(value, 10, &minTime);
986 if (ret < 0)
987 {
988 /* If the input value is greater than max value of datatype, then also
989 kstrtou8 fails */
990 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
991 "%s: kstrtou8 failed range [%d - %d]", __func__,
992 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
993 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
994 ret = -EINVAL;
995 goto exit;
996 }
997
998 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
999 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1000 {
1001 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1002 "scan min channel time value %d is out of range"
1003 " (Min: %d Max: %d)", minTime,
1004 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1005 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1006 ret = -EINVAL;
1007 goto exit;
1008 }
1009
1010 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1011 "%s: Received Command to change channel min time = %d", __func__, minTime);
1012
1013 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1014 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1015 }
1016 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1017 {
1018 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1019 char extra[32];
1020 tANI_U8 len = 0;
1021
1022 /* value is interms of msec */
1023 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1024 if (copy_to_user(priv_data.buf, &extra, len + 1))
1025 {
1026 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1027 "%s: failed to copy data to user buffer", __func__);
1028 ret = -EFAULT;
1029 goto exit;
1030 }
1031 }
1032 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1033 {
1034 tANI_U8 *value = command;
1035 tANI_U8 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
1036
1037 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1038 value = value + 19;
1039 /* Convert the value from ascii to integer */
1040 ret = kstrtou8(value, 10, &maxTime);
1041 if (ret < 0)
1042 {
1043 /* If the input value is greater than max value of datatype, then also
1044 kstrtou8 fails */
1045 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1046 "%s: kstrtou8 failed range [%d - %d]", __func__,
1047 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1048 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1049 ret = -EINVAL;
1050 goto exit;
1051 }
1052
1053 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1054 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1055 {
1056 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1057 "lfr mode value %d is out of range"
1058 " (Min: %d Max: %d)", maxTime,
1059 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1060 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1061 ret = -EINVAL;
1062 goto exit;
1063 }
1064
1065 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1066 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1067
1068 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
1069 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1070 }
1071 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1072 {
1073 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1074 char extra[32];
1075 tANI_U8 len = 0;
1076
1077 /* value is interms of msec */
1078 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1079 if (copy_to_user(priv_data.buf, &extra, len + 1))
1080 {
1081 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1082 "%s: failed to copy data to user buffer", __func__);
1083 ret = -EFAULT;
1084 goto exit;
1085 }
1086 }
1087 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1088 {
1089 tANI_U8 *value = command;
1090 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1091
1092 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1093 value = value + 16;
1094 /* Convert the value from ascii to integer */
1095 ret = kstrtou16(value, 10, &val);
1096 if (ret < 0)
1097 {
1098 /* If the input value is greater than max value of datatype, then also
1099 kstrtou16 fails */
1100 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1101 "%s: kstrtou16 failed range [%d - %d]", __func__,
1102 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1103 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1104 ret = -EINVAL;
1105 goto exit;
1106 }
1107
1108 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1109 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1110 {
1111 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1112 "scan home time value %d is out of range"
1113 " (Min: %d Max: %d)", val,
1114 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1115 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1116 ret = -EINVAL;
1117 goto exit;
1118 }
1119
1120 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1121 "%s: Received Command to change scan home time = %d", __func__, val);
1122
1123 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1124 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1125 }
1126 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1127 {
1128 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1129 char extra[32];
1130 tANI_U8 len = 0;
1131
1132 /* value is interms of msec */
1133 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1134 if (copy_to_user(priv_data.buf, &extra, len + 1))
1135 {
1136 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1137 "%s: failed to copy data to user buffer", __func__);
1138 ret = -EFAULT;
1139 goto exit;
1140 }
1141 }
1142 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1143 {
1144 tANI_U8 *value = command;
1145 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1146
1147 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1148 value = value + 17;
1149 /* Convert the value from ascii to integer */
1150 ret = kstrtou8(value, 10, &val);
1151 if (ret < 0)
1152 {
1153 /* If the input value is greater than max value of datatype, then also
1154 kstrtou8 fails */
1155 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1156 "%s: kstrtou8 failed range [%d - %d]", __func__,
1157 CFG_ROAM_INTRA_BAND_MIN,
1158 CFG_ROAM_INTRA_BAND_MAX);
1159 ret = -EINVAL;
1160 goto exit;
1161 }
1162
1163 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1164 (val > CFG_ROAM_INTRA_BAND_MAX))
1165 {
1166 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1167 "intra band mode value %d is out of range"
1168 " (Min: %d Max: %d)", val,
1169 CFG_ROAM_INTRA_BAND_MIN,
1170 CFG_ROAM_INTRA_BAND_MAX);
1171 ret = -EINVAL;
1172 goto exit;
1173 }
1174
1175 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1176 "%s: Received Command to change intra band = %d", __func__, val);
1177
1178 pHddCtx->cfg_ini->nRoamIntraBand = val;
1179 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1180 }
1181 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1182 {
1183 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1184 char extra[32];
1185 tANI_U8 len = 0;
1186
1187 /* value is interms of msec */
1188 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1189 if (copy_to_user(priv_data.buf, &extra, len + 1))
1190 {
1191 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1192 "%s: failed to copy data to user buffer", __func__);
1193 ret = -EFAULT;
1194 goto exit;
1195 }
1196 }
1197
1198#endif
1199#ifdef FEATURE_WLAN_LFR
1200 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1201 {
1202 tANI_U8 *value = command;
1203 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1204
1205 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1206 value = value + 12;
1207 /* Convert the value from ascii to integer */
1208 ret = kstrtou8(value, 10, &lfrMode);
1209 if (ret < 0)
1210 {
1211 /* If the input value is greater than max value of datatype, then also
1212 kstrtou8 fails */
1213 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1214 "%s: kstrtou8 failed range [%d - %d]", __func__,
1215 CFG_LFR_FEATURE_ENABLED_MIN,
1216 CFG_LFR_FEATURE_ENABLED_MAX);
1217 ret = -EINVAL;
1218 goto exit;
1219 }
1220
1221 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1222 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1223 {
1224 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1225 "lfr mode value %d is out of range"
1226 " (Min: %d Max: %d)", lfrMode,
1227 CFG_LFR_FEATURE_ENABLED_MIN,
1228 CFG_LFR_FEATURE_ENABLED_MAX);
1229 ret = -EINVAL;
1230 goto exit;
1231 }
1232
1233 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1234 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1235
1236 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1237 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1238 }
1239#endif
1240#ifdef WLAN_FEATURE_VOWIFI_11R
1241 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1242 {
1243 tANI_U8 *value = command;
1244 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1245
1246 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1247 value = value + 18;
1248 /* Convert the value from ascii to integer */
1249 ret = kstrtou8(value, 10, &ft);
1250 if (ret < 0)
1251 {
1252 /* If the input value is greater than max value of datatype, then also
1253 kstrtou8 fails */
1254 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1255 "%s: kstrtou8 failed range [%d - %d]", __func__,
1256 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1257 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1258 ret = -EINVAL;
1259 goto exit;
1260 }
1261
1262 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1263 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1264 {
1265 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1266 "ft mode value %d is out of range"
1267 " (Min: %d Max: %d)", ft,
1268 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1269 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1270 ret = -EINVAL;
1271 goto exit;
1272 }
1273
1274 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1275 "%s: Received Command to change ft mode = %d", __func__, ft);
1276
1277 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1278 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1279 }
1280#endif
1281#ifdef FEATURE_WLAN_CCX
1282 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1283 {
1284 tANI_U8 *value = command;
1285 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1286
1287 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1288 value = value + 11;
1289 /* Convert the value from ascii to integer */
1290 ret = kstrtou8(value, 10, &ccxMode);
1291 if (ret < 0)
1292 {
1293 /* If the input value is greater than max value of datatype, then also
1294 kstrtou8 fails */
1295 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1296 "%s: kstrtou8 failed range [%d - %d]", __func__,
1297 CFG_CCX_FEATURE_ENABLED_MIN,
1298 CFG_CCX_FEATURE_ENABLED_MAX);
1299 ret = -EINVAL;
1300 goto exit;
1301 }
1302
1303 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1304 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1305 {
1306 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1307 "Ccx mode value %d is out of range"
1308 " (Min: %d Max: %d)", ccxMode,
1309 CFG_CCX_FEATURE_ENABLED_MIN,
1310 CFG_CCX_FEATURE_ENABLED_MAX);
1311 ret = -EINVAL;
1312 goto exit;
1313 }
1314
1315 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1316 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1317
1318 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1319 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1320 }
1321#endif
1322#ifdef FEATURE_WLAN_OKC
1323 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1324 {
1325 tANI_U8 *value = command;
1326 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1327
1328 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1329 value = value + 11;
1330 /* Convert the value from ascii to integer */
1331 ret = kstrtou8(value, 10, &okcMode);
1332 if (ret < 0)
1333 {
1334 /* If the input value is greater than max value of datatype, then also
1335 kstrtou8 fails */
1336 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1337 "%s: kstrtou8 failed range [%d - %d]", __func__,
1338 CFG_OKC_FEATURE_ENABLED_MIN,
1339 CFG_OKC_FEATURE_ENABLED_MAX);
1340 ret = -EINVAL;
1341 goto exit;
1342 }
1343
1344 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1345 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1346 {
1347 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1348 "Okc mode value %d is out of range"
1349 " (Min: %d Max: %d)", okcMode,
1350 CFG_OKC_FEATURE_ENABLED_MIN,
1351 CFG_OKC_FEATURE_ENABLED_MAX);
1352 ret = -EINVAL;
1353 goto exit;
1354 }
1355
1356 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1357 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1358
1359 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1360 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001361#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001362 else {
1363 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
1364 __func__, command);
1365 }
1366
Jeff Johnson295189b2012-06-20 16:38:30 -07001367 }
1368exit:
1369 if (command)
1370 {
1371 kfree(command);
1372 }
1373 return ret;
1374}
1375
Srinivas Girigowdade697412013-02-14 16:31:48 -08001376#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1377void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
1378{
1379 eCsrBand band = -1;
1380 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
1381 switch (band)
1382 {
1383 case eCSR_BAND_ALL:
1384 *pBand = WLAN_HDD_UI_BAND_AUTO;
1385 break;
1386
1387 case eCSR_BAND_24:
1388 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
1389 break;
1390
1391 case eCSR_BAND_5G:
1392 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
1393 break;
1394
1395 default:
1396 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
1397 *pBand = -1;
1398 break;
1399 }
1400}
1401
1402/**---------------------------------------------------------------------------
1403
1404 \brief hdd_parse_countryrev() - HDD Parse country code revision
1405
1406 This function parses the country code revision passed in the format
1407 SETCOUNTRYREV<space><Country code><space>revision
1408
1409 \param - pValue Pointer to input country code revision
1410 \param - pCountryCode Pointer to local output array to record country code
1411 \param - pRevision Pointer to store revision integer number
1412
1413 \return - 0 for success non-zero for failure
1414
1415 --------------------------------------------------------------------------*/
1416VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
1417{
1418 tANI_U8 *inPtr = pValue;
1419 int tempInt;
1420
1421 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1422 /*no argument after the command*/
1423 if (NULL == inPtr)
1424 {
1425 return -EINVAL;
1426 }
1427
1428 /*no space after the command*/
1429 else if (SPACE_ASCII_VALUE != *inPtr)
1430 {
1431 return -EINVAL;
1432 }
1433
1434 /*removing empty spaces*/
1435 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
1436
1437 /*no argument followed by spaces*/
1438 if ('\0' == *inPtr)
1439 {
1440 return -EINVAL;
1441 }
1442
1443 /*getting the first argument ie the country code */
1444 sscanf(inPtr, "%s ", pCountryCode);
1445
1446 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1447 "Country code is : %s", pCountryCode);
1448
1449 /*inPtr pointing to the beginning of first space after country code */
1450 inPtr = strpbrk( inPtr, " " );
1451 /*no revision number after the country code argument */
1452 if (NULL == inPtr)
1453 {
1454 return -EINVAL;
1455 }
1456
1457 inPtr++;
1458
1459 /*removing empty space*/
1460 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1461
1462 /*no channel list after the number of channels argument and spaces*/
1463 if (0 == strncmp(pCountryCode, "KR", 2))
1464 {
1465 if ('\0' == *inPtr)
1466 {
1467 return -EINVAL;
1468 }
1469
1470 sscanf(inPtr, "%d", &tempInt);
1471 *pRevision = tempInt;
1472 }
1473 else
1474 {
1475 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1476 "Revision input is required only for Country KR");
1477 return -EINVAL;
1478 }
1479 return VOS_STATUS_SUCCESS;
1480}
1481
1482/**---------------------------------------------------------------------------
1483
1484 \brief hdd_parse_channellist() - HDD Parse channel list
1485
1486 This function parses the channel list passed in the format
1487 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001488 if the Number of channels (N) does not match with the actual number of channels passed
1489 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
1490 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
1491 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
1492 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08001493
1494 \param - pValue Pointer to input channel list
1495 \param - ChannelList Pointer to local output array to record channel list
1496 \param - pNumChannels Pointer to number of roam scan channels
1497
1498 \return - 0 for success non-zero for failure
1499
1500 --------------------------------------------------------------------------*/
1501VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
1502{
1503 tANI_U8 *inPtr = pValue;
1504 int tempInt;
1505 int j = 0;
1506 int v = 0;
1507 char buf[32];
1508
1509 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1510 /*no argument after the command*/
1511 if (NULL == inPtr)
1512 {
1513 return -EINVAL;
1514 }
1515
1516 /*no space after the command*/
1517 else if (SPACE_ASCII_VALUE != *inPtr)
1518 {
1519 return -EINVAL;
1520 }
1521
1522 /*removing empty spaces*/
1523 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
1524
1525 /*no argument followed by spaces*/
1526 if ('\0' == *inPtr)
1527 {
1528 return -EINVAL;
1529 }
1530
1531 /*getting the first argument ie the number of channels*/
1532 sscanf(inPtr, "%s ", buf);
1533 v = kstrtos32(buf, 10, &tempInt);
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001534 if ((v < 0) || (tempInt <= 0)) return -EINVAL;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001535
1536 *pNumChannels = tempInt;
1537
1538 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1539 "Number of channels are: %d", *pNumChannels);
1540
1541 for (j = 0; j < (*pNumChannels); j++)
1542 {
1543 /*inPtr pointing to the beginning of first space after number of channels*/
1544 inPtr = strpbrk( inPtr, " " );
1545 /*no channel list after the number of channels argument*/
1546 if (NULL == inPtr)
1547 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001548 if (0 != j)
1549 {
1550 *pNumChannels = j;
1551 return VOS_STATUS_SUCCESS;
1552 }
1553 else
1554 {
1555 return -EINVAL;
1556 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001557 }
1558
1559 /*removing empty space*/
1560 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1561
1562 /*no channel list after the number of channels argument and spaces*/
1563 if ( '\0' == *inPtr )
1564 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001565 if (0 != j)
1566 {
1567 *pNumChannels = j;
1568 return VOS_STATUS_SUCCESS;
1569 }
1570 else
1571 {
1572 return -EINVAL;
1573 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001574 }
1575
1576 sscanf(inPtr, "%s ", buf);
1577 v = kstrtos32(buf, 10, &tempInt);
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001578 if ((v < 0) || (tempInt <= 0)) return -EINVAL;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001579 pChannelList[j] = tempInt;
1580
1581 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1582 "Channel %d added to preferred channel list",
1583 pChannelList[j] );
1584 }
1585
Srinivas Girigowdade697412013-02-14 16:31:48 -08001586 return VOS_STATUS_SUCCESS;
1587}
1588
1589#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001590/**---------------------------------------------------------------------------
1591
1592 \brief hdd_open() - HDD Open function
1593
1594 This is called in response to ifconfig up
1595
1596 \param - dev Pointer to net_device structure
1597
1598 \return - 0 for success non-zero for failure
1599
1600 --------------------------------------------------------------------------*/
1601int hdd_open (struct net_device *dev)
1602{
1603 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1604 hdd_context_t *pHddCtx;
1605 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1606 VOS_STATUS status;
1607 v_BOOL_t in_standby = TRUE;
1608
1609 if (NULL == pAdapter)
1610 {
1611 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001612 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001613 return -ENODEV;
1614 }
1615
1616 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1617 if (NULL == pHddCtx)
1618 {
1619 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001620 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001621 return -ENODEV;
1622 }
1623
1624 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1625 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1626 {
1627 if( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
1628 {
1629 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of "
1630 "standby", __func__, pAdapter->device_mode);
1631 in_standby = FALSE;
1632 break;
1633 }
1634 else
1635 {
1636 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1637 pAdapterNode = pNext;
1638 }
1639 }
1640
1641 if (TRUE == in_standby)
1642 {
1643 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
1644 {
1645 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
1646 "wlan out of power save", __func__);
1647 return -EINVAL;
1648 }
1649 }
1650
1651 pAdapter->event_flags |= DEVICE_IFACE_OPENED;
1652 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
1653 {
1654 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001655 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001656 /* Enable TX queues only when we are connected */
1657 netif_tx_start_all_queues(dev);
1658 }
1659
1660 return 0;
1661}
1662
1663int hdd_mon_open (struct net_device *dev)
1664{
1665 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1666
1667 if(pAdapter == NULL) {
1668 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001669 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001670 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001671 }
1672
1673 netif_start_queue(dev);
1674
1675 return 0;
1676}
1677/**---------------------------------------------------------------------------
1678
1679 \brief hdd_stop() - HDD stop function
1680
1681 This is called in response to ifconfig down
1682
1683 \param - dev Pointer to net_device structure
1684
1685 \return - 0 for success non-zero for failure
1686
1687 --------------------------------------------------------------------------*/
1688
1689int hdd_stop (struct net_device *dev)
1690{
1691 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1692 hdd_context_t *pHddCtx;
1693 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1694 VOS_STATUS status;
1695 v_BOOL_t enter_standby = TRUE;
1696
1697 ENTER();
1698
1699 if (NULL == pAdapter)
1700 {
1701 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001702 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001703 return -ENODEV;
1704 }
1705
1706 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1707 if (NULL == pHddCtx)
1708 {
1709 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001710 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001711 return -ENODEV;
1712 }
1713
1714 pAdapter->event_flags &= ~(DEVICE_IFACE_OPENED);
1715 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
1716 netif_tx_disable(pAdapter->dev);
1717 netif_carrier_off(pAdapter->dev);
1718
1719
1720 /* SoftAP ifaces should never go in power save mode
1721 making sure same here. */
1722 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
1723 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001724 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001725 )
1726 {
1727 /* SoftAP mode, so return from here */
1728 EXIT();
1729 return 0;
1730 }
1731
1732 /* Find if any iface is up then
1733 if any iface is up then can't put device to sleep/ power save mode. */
1734 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1735 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1736 {
1737 if ( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
1738 {
1739 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
1740 "put device to sleep", __func__, pAdapter->device_mode);
1741 enter_standby = FALSE;
1742 break;
1743 }
1744 else
1745 {
1746 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1747 pAdapterNode = pNext;
1748 }
1749 }
1750
1751 if (TRUE == enter_standby)
1752 {
1753 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
1754 "entering standby", __func__);
1755 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
1756 {
1757 /*log and return success*/
1758 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
1759 "wlan in power save", __func__);
1760 }
1761 }
1762
1763 EXIT();
1764 return 0;
1765}
1766
1767/**---------------------------------------------------------------------------
1768
1769 \brief hdd_uninit() - HDD uninit function
1770
1771 This is called during the netdev unregister to uninitialize all data
1772associated with the device
1773
1774 \param - dev Pointer to net_device structure
1775
1776 \return - void
1777
1778 --------------------------------------------------------------------------*/
1779static void hdd_uninit (struct net_device *dev)
1780{
1781 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1782
1783 ENTER();
1784
1785 do
1786 {
1787 if (NULL == pAdapter)
1788 {
1789 hddLog(VOS_TRACE_LEVEL_FATAL,
1790 "%s: NULL pAdapter", __func__);
1791 break;
1792 }
1793
1794 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1795 {
1796 hddLog(VOS_TRACE_LEVEL_FATAL,
1797 "%s: Invalid magic", __func__);
1798 break;
1799 }
1800
1801 if (NULL == pAdapter->pHddCtx)
1802 {
1803 hddLog(VOS_TRACE_LEVEL_FATAL,
1804 "%s: NULL pHddCtx", __func__);
1805 break;
1806 }
1807
1808 if (dev != pAdapter->dev)
1809 {
1810 hddLog(VOS_TRACE_LEVEL_FATAL,
1811 "%s: Invalid device reference", __func__);
1812 /* we haven't validated all cases so let this go for now */
1813 }
1814
1815 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
1816
1817 /* after uninit our adapter structure will no longer be valid */
1818 pAdapter->dev = NULL;
1819 pAdapter->magic = 0;
1820 } while (0);
1821
1822 EXIT();
1823}
1824
1825/**---------------------------------------------------------------------------
1826
1827 \brief hdd_release_firmware() -
1828
1829 This function calls the release firmware API to free the firmware buffer.
1830
1831 \param - pFileName Pointer to the File Name.
1832 pCtx - Pointer to the adapter .
1833
1834
1835 \return - 0 for success, non zero for failure
1836
1837 --------------------------------------------------------------------------*/
1838
1839VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
1840{
1841 VOS_STATUS status = VOS_STATUS_SUCCESS;
1842 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1843 ENTER();
1844
1845
1846 if (!strcmp(WLAN_FW_FILE, pFileName)) {
1847
1848 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
1849
1850 if(pHddCtx->fw) {
1851 release_firmware(pHddCtx->fw);
1852 pHddCtx->fw = NULL;
1853 }
1854 else
1855 status = VOS_STATUS_E_FAILURE;
1856 }
1857 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
1858 if(pHddCtx->nv) {
1859 release_firmware(pHddCtx->nv);
1860 pHddCtx->nv = NULL;
1861 }
1862 else
1863 status = VOS_STATUS_E_FAILURE;
1864
1865 }
1866
1867 EXIT();
1868 return status;
1869}
1870
1871/**---------------------------------------------------------------------------
1872
1873 \brief hdd_request_firmware() -
1874
1875 This function reads the firmware file using the request firmware
1876 API and returns the the firmware data and the firmware file size.
1877
1878 \param - pfileName - Pointer to the file name.
1879 - pCtx - Pointer to the adapter .
1880 - ppfw_data - Pointer to the pointer of the firmware data.
1881 - pSize - Pointer to the file size.
1882
1883 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
1884
1885 --------------------------------------------------------------------------*/
1886
1887
1888VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
1889{
1890 int status;
1891 VOS_STATUS retval = VOS_STATUS_SUCCESS;
1892 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1893 ENTER();
1894
1895 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
1896
1897 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
1898
1899 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1900 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
1901 __func__, pfileName);
1902 retval = VOS_STATUS_E_FAILURE;
1903 }
1904
1905 else {
1906 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
1907 *pSize = pHddCtx->fw->size;
1908 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
1909 __func__, *pSize);
1910 }
1911 }
1912 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
1913
1914 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
1915
1916 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
1917 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
1918 __func__, pfileName);
1919 retval = VOS_STATUS_E_FAILURE;
1920 }
1921
1922 else {
1923 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
1924 *pSize = pHddCtx->nv->size;
1925 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
1926 __func__, *pSize);
1927 }
1928 }
1929
1930 EXIT();
1931 return retval;
1932}
1933/**---------------------------------------------------------------------------
1934 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
1935
1936 This is the function invoked by SME to inform the result of a full power
1937 request issued by HDD
1938
1939 \param - callbackcontext - Pointer to cookie
1940 status - result of request
1941
1942 \return - None
1943
1944--------------------------------------------------------------------------*/
1945void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
1946{
1947 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
1948
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001949 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001950 if(&pHddCtx->full_pwr_comp_var)
1951 {
1952 complete(&pHddCtx->full_pwr_comp_var);
1953 }
1954}
1955
1956/**---------------------------------------------------------------------------
1957
1958 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
1959
1960 This is the function invoked by SME to inform the result of BMPS
1961 request issued by HDD
1962
1963 \param - callbackcontext - Pointer to cookie
1964 status - result of request
1965
1966 \return - None
1967
1968--------------------------------------------------------------------------*/
1969void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
1970{
1971
1972 struct completion *completion_var = (struct completion*) callbackContext;
1973
1974 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
1975 if(completion_var != NULL)
1976 {
1977 complete(completion_var);
1978 }
1979}
1980
1981/**---------------------------------------------------------------------------
1982
1983 \brief hdd_get_cfg_file_size() -
1984
1985 This function reads the configuration file using the request firmware
1986 API and returns the configuration file size.
1987
1988 \param - pCtx - Pointer to the adapter .
1989 - pFileName - Pointer to the file name.
1990 - pBufSize - Pointer to the buffer size.
1991
1992 \return - 0 for success, non zero for failure
1993
1994 --------------------------------------------------------------------------*/
1995
1996VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
1997{
1998 int status;
1999 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2000
2001 ENTER();
2002
2003 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2004
2005 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2006 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2007 status = VOS_STATUS_E_FAILURE;
2008 }
2009 else {
2010 *pBufSize = pHddCtx->fw->size;
2011 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2012 release_firmware(pHddCtx->fw);
2013 pHddCtx->fw = NULL;
2014 }
2015
2016 EXIT();
2017 return VOS_STATUS_SUCCESS;
2018}
2019
2020/**---------------------------------------------------------------------------
2021
2022 \brief hdd_read_cfg_file() -
2023
2024 This function reads the configuration file using the request firmware
2025 API and returns the cfg data and the buffer size of the configuration file.
2026
2027 \param - pCtx - Pointer to the adapter .
2028 - pFileName - Pointer to the file name.
2029 - pBuffer - Pointer to the data buffer.
2030 - pBufSize - Pointer to the buffer size.
2031
2032 \return - 0 for success, non zero for failure
2033
2034 --------------------------------------------------------------------------*/
2035
2036VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2037 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2038{
2039 int status;
2040 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2041
2042 ENTER();
2043
2044 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2045
2046 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2047 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2048 return VOS_STATUS_E_FAILURE;
2049 }
2050 else {
2051 if(*pBufSize != pHddCtx->fw->size) {
2052 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2053 "file size", __func__);
2054 release_firmware(pHddCtx->fw);
2055 pHddCtx->fw = NULL;
2056 return VOS_STATUS_E_FAILURE;
2057 }
2058 else {
2059 if(pBuffer) {
2060 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2061 }
2062 release_firmware(pHddCtx->fw);
2063 pHddCtx->fw = NULL;
2064 }
2065 }
2066
2067 EXIT();
2068
2069 return VOS_STATUS_SUCCESS;
2070}
2071
2072/**---------------------------------------------------------------------------
2073
Jeff Johnson295189b2012-06-20 16:38:30 -07002074 \brief hdd_set_mac_address() -
2075
2076 This function sets the user specified mac address using
2077 the command ifconfig wlanX hw ether <mac adress>.
2078
2079 \param - dev - Pointer to the net device.
2080 - addr - Pointer to the sockaddr.
2081 \return - 0 for success, non zero for failure
2082
2083 --------------------------------------------------------------------------*/
2084
2085static int hdd_set_mac_address(struct net_device *dev, void *addr)
2086{
2087 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2088 struct sockaddr *psta_mac_addr = addr;
2089 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2090
2091 ENTER();
2092
2093 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2094
2095#ifdef HDD_SESSIONIZE
2096 // set the MAC address though the STA ID CFG.
2097 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2098 (v_U8_t *)&pAdapter->macAddressCurrent,
2099 sizeof( pAdapter->macAddressCurrent ),
2100 hdd_set_mac_addr_cb, VOS_FALSE );
2101#endif
2102
2103 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2104
2105 EXIT();
2106 return halStatus;
2107}
2108
2109tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2110{
2111 int i;
2112 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2113 {
2114 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2115 break;
2116 }
2117
2118 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2119 return NULL;
2120
2121 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2122 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2123}
2124
2125void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
2126{
2127 int i;
2128 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2129 {
2130 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
2131 {
2132 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
2133 break;
2134 }
2135 }
2136 return;
2137}
2138
2139#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2140 static struct net_device_ops wlan_drv_ops = {
2141 .ndo_open = hdd_open,
2142 .ndo_stop = hdd_stop,
2143 .ndo_uninit = hdd_uninit,
2144 .ndo_start_xmit = hdd_hard_start_xmit,
2145 .ndo_tx_timeout = hdd_tx_timeout,
2146 .ndo_get_stats = hdd_stats,
2147 .ndo_do_ioctl = hdd_ioctl,
2148 .ndo_set_mac_address = hdd_set_mac_address,
2149 .ndo_select_queue = hdd_select_queue,
2150#ifdef WLAN_FEATURE_PACKET_FILTERING
2151#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
2152 .ndo_set_rx_mode = hdd_set_multicast_list,
2153#else
2154 .ndo_set_multicast_list = hdd_set_multicast_list,
2155#endif //LINUX_VERSION_CODE
2156#endif
2157 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002158 static struct net_device_ops wlan_mon_drv_ops = {
2159 .ndo_open = hdd_mon_open,
2160 .ndo_stop = hdd_stop,
2161 .ndo_uninit = hdd_uninit,
2162 .ndo_start_xmit = hdd_mon_hard_start_xmit,
2163 .ndo_tx_timeout = hdd_tx_timeout,
2164 .ndo_get_stats = hdd_stats,
2165 .ndo_do_ioctl = hdd_ioctl,
2166 .ndo_set_mac_address = hdd_set_mac_address,
2167 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002168
2169#endif
2170
2171void hdd_set_station_ops( struct net_device *pWlanDev )
2172{
2173#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2174 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
2175 pWlanDev->netdev_ops = &wlan_drv_ops;
2176#else
2177 pWlanDev->open = hdd_open;
2178 pWlanDev->stop = hdd_stop;
2179 pWlanDev->uninit = hdd_uninit;
2180 pWlanDev->hard_start_xmit = NULL;
2181 pWlanDev->tx_timeout = hdd_tx_timeout;
2182 pWlanDev->get_stats = hdd_stats;
2183 pWlanDev->do_ioctl = hdd_ioctl;
2184 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
2185 pWlanDev->set_mac_address = hdd_set_mac_address;
2186#endif
2187}
2188
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002189static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07002190{
2191 struct net_device *pWlanDev = NULL;
2192 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002193 /*
2194 * cfg80211 initialization and registration....
2195 */
2196 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
2197
Jeff Johnson295189b2012-06-20 16:38:30 -07002198 if(pWlanDev != NULL)
2199 {
2200
2201 //Save the pointer to the net_device in the HDD adapter
2202 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
2203
Jeff Johnson295189b2012-06-20 16:38:30 -07002204 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
2205
2206 pAdapter->dev = pWlanDev;
2207 pAdapter->pHddCtx = pHddCtx;
2208 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
2209
2210 init_completion(&pAdapter->session_open_comp_var);
2211 init_completion(&pAdapter->session_close_comp_var);
2212 init_completion(&pAdapter->disconnect_comp_var);
2213 init_completion(&pAdapter->linkup_event_var);
2214 init_completion(&pAdapter->cancel_rem_on_chan_var);
2215 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07002216#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2217 init_completion(&pAdapter->offchannel_tx_event);
2218#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002219 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002220#ifdef FEATURE_WLAN_TDLS
2221 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002222 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002223 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002224#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002225 init_completion(&pHddCtx->mc_sus_event_var);
2226 init_completion(&pHddCtx->tx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07002227 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07002228
Jeff Johnson295189b2012-06-20 16:38:30 -07002229 pAdapter->isLinkUpSvcNeeded = FALSE;
2230 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
2231 //Init the net_device structure
2232 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2233
2234 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
2235 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
2236 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
2237 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
2238
2239 hdd_set_station_ops( pAdapter->dev );
2240
2241 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002242 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
2243 pAdapter->wdev.wiphy = pHddCtx->wiphy;
2244 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002245 /* set pWlanDev's parent to underlying device */
2246 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
2247 }
2248
2249 return pAdapter;
2250}
2251
2252VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
2253{
2254 struct net_device *pWlanDev = pAdapter->dev;
2255 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2256 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2257 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2258
2259 if( rtnl_lock_held )
2260 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08002261 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07002262 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
2263 {
2264 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
2265 return VOS_STATUS_E_FAILURE;
2266 }
2267 }
2268 if (register_netdevice(pWlanDev))
2269 {
2270 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
2271 return VOS_STATUS_E_FAILURE;
2272 }
2273 }
2274 else
2275 {
2276 if(register_netdev(pWlanDev))
2277 {
2278 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
2279 return VOS_STATUS_E_FAILURE;
2280 }
2281 }
2282 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
2283
2284 return VOS_STATUS_SUCCESS;
2285}
2286
2287eHalStatus hdd_smeCloseSessionCallback(void *pContext)
2288{
2289 if(pContext != NULL)
2290 {
2291 clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags);
2292
2293 /* need to make sure all of our scheduled work has completed.
2294 * This callback is called from MC thread context, so it is safe to
2295 * to call below flush workqueue API from here.
2296 */
2297 flush_scheduled_work();
2298 complete(&((hdd_adapter_t*)pContext)->session_close_comp_var);
2299 }
2300 return eHAL_STATUS_SUCCESS;
2301}
2302
2303VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
2304{
2305 struct net_device *pWlanDev = pAdapter->dev;
2306 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2307 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2308 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2309 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2310 int rc = 0;
2311
2312 INIT_COMPLETION(pAdapter->session_open_comp_var);
2313 //Open a SME session for future operation
2314 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
2315 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
2316 if ( !HAL_STATUS_SUCCESS( halStatus ) )
2317 {
2318 hddLog(VOS_TRACE_LEVEL_FATAL,
2319 "sme_OpenSession() failed with status code %08d [x%08lx]",
2320 halStatus, halStatus );
2321 status = VOS_STATUS_E_FAILURE;
2322 goto error_sme_open;
2323 }
2324
2325 //Block on a completion variable. Can't wait forever though.
2326 rc = wait_for_completion_interruptible_timeout(
2327 &pAdapter->session_open_comp_var,
2328 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2329 if (!rc)
2330 {
2331 hddLog(VOS_TRACE_LEVEL_FATAL,
2332 "Session is not opened within timeout period code %08d", rc );
2333 status = VOS_STATUS_E_FAILURE;
2334 goto error_sme_open;
2335 }
2336
2337 // Register wireless extensions
2338 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
2339 {
2340 hddLog(VOS_TRACE_LEVEL_FATAL,
2341 "hdd_register_wext() failed with status code %08d [x%08lx]",
2342 halStatus, halStatus );
2343 status = VOS_STATUS_E_FAILURE;
2344 goto error_register_wext;
2345 }
2346 //Safe to register the hard_start_xmit function again
2347#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2348 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
2349#else
2350 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
2351#endif
2352
2353 //Set the Connection State to Not Connected
2354 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2355
2356 //Set the default operation channel
2357 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
2358
2359 /* Make the default Auth Type as OPEN*/
2360 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2361
2362 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
2363 {
2364 hddLog(VOS_TRACE_LEVEL_FATAL,
2365 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
2366 status, status );
2367 goto error_init_txrx;
2368 }
2369
2370 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2371
2372 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
2373 {
2374 hddLog(VOS_TRACE_LEVEL_FATAL,
2375 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
2376 status, status );
2377 goto error_wmm_init;
2378 }
2379
2380 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2381
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002382#ifdef FEATURE_WLAN_TDLS
2383 if(0 != wlan_hdd_tdls_init(pAdapter))
2384 {
2385 status = VOS_STATUS_E_FAILURE;
2386 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
2387 goto error_tdls_init;
2388 }
2389 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2390#endif
2391
Jeff Johnson295189b2012-06-20 16:38:30 -07002392 return VOS_STATUS_SUCCESS;
2393
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002394#ifdef FEATURE_WLAN_TDLS
2395error_tdls_init:
2396 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2397 hdd_wmm_adapter_close(pAdapter);
2398#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002399error_wmm_init:
2400 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2401 hdd_deinit_tx_rx(pAdapter);
2402error_init_txrx:
2403 hdd_UnregisterWext(pWlanDev);
2404error_register_wext:
2405 if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
2406 {
2407 INIT_COMPLETION(pAdapter->session_close_comp_var);
2408 if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
2409 pAdapter->sessionId,
2410 hdd_smeCloseSessionCallback, pAdapter ) )
2411 {
2412 //Block on a completion variable. Can't wait forever though.
2413 wait_for_completion_interruptible_timeout(
2414 &pAdapter->session_close_comp_var,
2415 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2416 }
2417}
2418error_sme_open:
2419 return status;
2420}
2421
Jeff Johnson295189b2012-06-20 16:38:30 -07002422void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2423{
2424 hdd_cfg80211_state_t *cfgState;
2425
2426 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
2427
2428 if( NULL != cfgState->buf )
2429 {
2430 int rc;
2431 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
2432 rc = wait_for_completion_interruptible_timeout(
2433 &pAdapter->tx_action_cnf_event,
2434 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2435 if(!rc)
2436 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08002437 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07002438 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
2439 }
2440 }
2441 return;
2442}
Jeff Johnson295189b2012-06-20 16:38:30 -07002443
2444void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2445{
2446 ENTER();
2447 switch ( pAdapter->device_mode )
2448 {
2449 case WLAN_HDD_INFRA_STATION:
2450 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002451 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002452 {
2453 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2454 {
2455 hdd_deinit_tx_rx( pAdapter );
2456 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2457 }
2458
2459 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
2460 {
2461 hdd_wmm_adapter_close( pAdapter );
2462 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2463 }
2464
Jeff Johnson295189b2012-06-20 16:38:30 -07002465 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002466#ifdef FEATURE_WLAN_TDLS
2467 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
2468 {
2469 wlan_hdd_tdls_exit(pAdapter);
2470 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2471 }
2472#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002473
2474 break;
2475 }
2476
2477 case WLAN_HDD_SOFTAP:
2478 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002479 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002480 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002481
2482 hdd_unregister_hostapd(pAdapter);
2483 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07002484 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07002485 break;
2486 }
2487
2488 case WLAN_HDD_MONITOR:
2489 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002490 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07002491 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2492 {
2493 hdd_deinit_tx_rx( pAdapter );
2494 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2495 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002496 if(NULL != pAdapterforTx)
2497 {
2498 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
2499 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002500 break;
2501 }
2502
2503
2504 default:
2505 break;
2506 }
2507
2508 EXIT();
2509}
2510
2511void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
2512{
2513 struct net_device *pWlanDev = pAdapter->dev;
2514
2515 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
2516 if( rtnl_held )
2517 {
2518 unregister_netdevice(pWlanDev);
2519 }
2520 else
2521 {
2522 unregister_netdev(pWlanDev);
2523 }
2524 // note that the pAdapter is no longer valid at this point
2525 // since the memory has been reclaimed
2526 }
2527
2528}
2529
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08002530void hdd_set_pwrparams(hdd_context_t *pHddCtx)
2531{
2532 tSirSetPowerParamsReq powerRequest = { 0 };
2533
2534 powerRequest.uIgnoreDTIM = 1;
2535
2536 if (pHddCtx->cfg_ini->enableModulatedDTIM)
2537 {
2538 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
2539 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2540 }
2541 else
2542 {
2543 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
2544 }
2545
2546 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
2547 *specified during Enter/Exit BMPS when LCD off*/
2548 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2549 NULL, eANI_BOOLEAN_FALSE);
2550 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2551 NULL, eANI_BOOLEAN_FALSE);
2552
2553 /* switch to the DTIM specified in cfg.ini */
2554 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2555 "Switch to DTIM%d", powerRequest.uListenInterval);
2556 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2557
2558}
2559
2560void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
2561{
2562 /*Switch back to DTIM 1*/
2563 tSirSetPowerParamsReq powerRequest = { 0 };
2564
2565 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
2566 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2567
2568 /* Update ignoreDTIM and ListedInterval in CFG with default values */
2569 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2570 NULL, eANI_BOOLEAN_FALSE);
2571 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2572 NULL, eANI_BOOLEAN_FALSE);
2573
2574 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2575 "Switch to DTIM%d",powerRequest.uListenInterval);
2576 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2577
2578}
2579
Jeff Johnson295189b2012-06-20 16:38:30 -07002580VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
2581{
2582 VOS_STATUS status = VOS_STATUS_SUCCESS;
2583
2584 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2585 {
2586 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2587 }
2588
2589 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2590 {
2591 sme_StartAutoBmpsTimer(pHddCtx->hHal);
2592 }
2593
2594 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2595 {
2596 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2597 }
2598
2599 return status;
2600}
2601
2602VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
2603{
2604 hdd_adapter_t *pAdapter = NULL;
2605 eHalStatus halStatus;
2606 VOS_STATUS status = VOS_STATUS_E_INVAL;
2607 v_BOOL_t disableBmps = FALSE;
2608 v_BOOL_t disableImps = FALSE;
2609
2610 switch(session_type)
2611 {
2612 case WLAN_HDD_INFRA_STATION:
2613 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002614 case WLAN_HDD_P2P_CLIENT:
2615 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002616 //Exit BMPS -> Is Sta/P2P Client is already connected
2617 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
2618 if((NULL != pAdapter)&&
2619 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2620 {
2621 disableBmps = TRUE;
2622 }
2623
2624 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
2625 if((NULL != pAdapter)&&
2626 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2627 {
2628 disableBmps = TRUE;
2629 }
2630
2631 //Exit both Bmps and Imps incase of Go/SAP Mode
2632 if((WLAN_HDD_SOFTAP == session_type) ||
2633 (WLAN_HDD_P2P_GO == session_type))
2634 {
2635 disableBmps = TRUE;
2636 disableImps = TRUE;
2637 }
2638
2639 if(TRUE == disableImps)
2640 {
2641 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2642 {
2643 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2644 }
2645 }
2646
2647 if(TRUE == disableBmps)
2648 {
2649 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2650 {
2651 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2652
2653 if(eHAL_STATUS_SUCCESS != halStatus)
2654 {
2655 status = VOS_STATUS_E_FAILURE;
2656 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
2657 VOS_ASSERT(0);
2658 return status;
2659 }
2660 }
2661
2662 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2663 {
2664 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
2665
2666 if(eHAL_STATUS_SUCCESS != halStatus)
2667 {
2668 status = VOS_STATUS_E_FAILURE;
2669 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
2670 VOS_ASSERT(0);
2671 return status;
2672 }
2673 }
2674 }
2675
2676 if((TRUE == disableBmps) ||
2677 (TRUE == disableImps))
2678 {
2679 /* Now, get the chip into Full Power now */
2680 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
2681 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
2682 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
2683
2684 if(halStatus != eHAL_STATUS_SUCCESS)
2685 {
2686 if(halStatus == eHAL_STATUS_PMC_PENDING)
2687 {
2688 //Block on a completion variable. Can't wait forever though
2689 wait_for_completion_interruptible_timeout(
2690 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
2691 }
2692 else
2693 {
2694 status = VOS_STATUS_E_FAILURE;
2695 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
2696 VOS_ASSERT(0);
2697 return status;
2698 }
2699 }
2700
2701 status = VOS_STATUS_SUCCESS;
2702 }
2703
2704 break;
2705 }
2706 return status;
2707}
2708
2709hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002710 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07002711 tANI_U8 rtnl_held )
2712{
2713 hdd_adapter_t *pAdapter = NULL;
2714 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
2715 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2716 VOS_STATUS exitbmpsStatus;
2717
2718 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
2719
2720 //Disable BMPS incase of Concurrency
2721 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
2722
2723 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
2724 {
2725 //Fail to Exit BMPS
2726 VOS_ASSERT(0);
2727 return NULL;
2728 }
2729
2730 switch(session_type)
2731 {
2732 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002733 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002734 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002735 {
2736 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2737
2738 if( NULL == pAdapter )
2739 return NULL;
2740
Jeff Johnsone7245742012-09-05 17:12:55 -07002741 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
2742 NL80211_IFTYPE_P2P_CLIENT:
2743 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07002744
Jeff Johnson295189b2012-06-20 16:38:30 -07002745 pAdapter->device_mode = session_type;
2746
2747 status = hdd_init_station_mode( pAdapter );
2748 if( VOS_STATUS_SUCCESS != status )
2749 goto err_free_netdev;
2750
2751 status = hdd_register_interface( pAdapter, rtnl_held );
2752 if( VOS_STATUS_SUCCESS != status )
2753 {
2754 hdd_deinit_adapter(pHddCtx, pAdapter);
2755 goto err_free_netdev;
2756 }
2757 //Stop the Interface TX queue.
2758 netif_tx_disable(pAdapter->dev);
2759 //netif_tx_disable(pWlanDev);
2760 netif_carrier_off(pAdapter->dev);
2761
2762 break;
2763 }
2764
Jeff Johnson295189b2012-06-20 16:38:30 -07002765 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002766 case WLAN_HDD_SOFTAP:
2767 {
2768 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
2769 if( NULL == pAdapter )
2770 return NULL;
2771
Jeff Johnson295189b2012-06-20 16:38:30 -07002772 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
2773 NL80211_IFTYPE_AP:
2774 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002775 pAdapter->device_mode = session_type;
2776
2777 status = hdd_init_ap_mode(pAdapter);
2778 if( VOS_STATUS_SUCCESS != status )
2779 goto err_free_netdev;
2780
2781 status = hdd_register_hostapd( pAdapter, rtnl_held );
2782 if( VOS_STATUS_SUCCESS != status )
2783 {
2784 hdd_deinit_adapter(pHddCtx, pAdapter);
2785 goto err_free_netdev;
2786 }
2787
2788 netif_tx_disable(pAdapter->dev);
2789 netif_carrier_off(pAdapter->dev);
2790
2791 hdd_set_conparam( 1 );
2792 break;
2793 }
2794 case WLAN_HDD_MONITOR:
2795 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002796 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2797 if( NULL == pAdapter )
2798 return NULL;
2799
2800 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
2801 pAdapter->device_mode = session_type;
2802 status = hdd_register_interface( pAdapter, rtnl_held );
2803#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
2804 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
2805#else
2806 pAdapter->dev->open = hdd_mon_open;
2807 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
2808#endif
2809 hdd_init_tx_rx( pAdapter );
2810 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2811 //Set adapter to be used for data tx. It will use either GO or softap.
2812 pAdapter->sessionCtx.monitor.pAdapterForTx =
2813 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07002814 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
2815 {
2816 pAdapter->sessionCtx.monitor.pAdapterForTx =
2817 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
2818 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002819 /* This workqueue will be used to transmit management packet over
2820 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07002821 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
2822 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
2823 return NULL;
2824 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07002825
Jeff Johnson295189b2012-06-20 16:38:30 -07002826 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
2827 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07002828 }
2829 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002830 case WLAN_HDD_FTM:
2831 {
2832 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2833
2834 if( NULL == pAdapter )
2835 return NULL;
2836 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
2837 * message while loading driver in FTM mode. */
2838 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
2839 pAdapter->device_mode = session_type;
2840 status = hdd_register_interface( pAdapter, rtnl_held );
2841 }
2842 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002843 default:
2844 {
2845 VOS_ASSERT(0);
2846 return NULL;
2847 }
2848 }
2849
2850
2851 if( VOS_STATUS_SUCCESS == status )
2852 {
2853 //Add it to the hdd's session list.
2854 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
2855 if( NULL == pHddAdapterNode )
2856 {
2857 status = VOS_STATUS_E_NOMEM;
2858 }
2859 else
2860 {
2861 pHddAdapterNode->pAdapter = pAdapter;
2862 status = hdd_add_adapter_back ( pHddCtx,
2863 pHddAdapterNode );
2864 }
2865 }
2866
2867 if( VOS_STATUS_SUCCESS != status )
2868 {
2869 if( NULL != pAdapter )
2870 {
2871 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
2872 pAdapter = NULL;
2873 }
2874 if( NULL != pHddAdapterNode )
2875 {
2876 vos_mem_free( pHddAdapterNode );
2877 }
2878
2879 goto resume_bmps;
2880 }
2881
2882 if(VOS_STATUS_SUCCESS == status)
2883 {
2884 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
2885
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07002886 //Initialize the WoWL service
2887 if(!hdd_init_wowl(pAdapter))
2888 {
2889 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
2890 goto err_free_netdev;
2891 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002892 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002893 return pAdapter;
2894
2895err_free_netdev:
2896 free_netdev(pAdapter->dev);
2897 wlan_hdd_release_intf_addr( pHddCtx,
2898 pAdapter->macAddressCurrent.bytes );
2899
2900resume_bmps:
2901 //If bmps disabled enable it
2902 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
2903 {
2904 hdd_enable_bmps_imps(pHddCtx);
2905 }
2906 return NULL;
2907}
2908
2909VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
2910 tANI_U8 rtnl_held )
2911{
2912 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
2913 VOS_STATUS status;
2914
2915 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
2916 if( VOS_STATUS_SUCCESS != status )
2917 return status;
2918
2919 while ( pCurrent->pAdapter != pAdapter )
2920 {
2921 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
2922 if( VOS_STATUS_SUCCESS != status )
2923 break;
2924
2925 pCurrent = pNext;
2926 }
2927 pAdapterNode = pCurrent;
2928 if( VOS_STATUS_SUCCESS == status )
2929 {
2930 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2931 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
2932 hdd_remove_adapter( pHddCtx, pAdapterNode );
2933 vos_mem_free( pAdapterNode );
2934
Jeff Johnson295189b2012-06-20 16:38:30 -07002935
2936 /* If there is a single session of STA/P2P client, re-enable BMPS */
2937 if ((!vos_concurrent_sessions_running()) &&
2938 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
2939 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
2940 {
2941 hdd_enable_bmps_imps(pHddCtx);
2942 }
2943
2944 return VOS_STATUS_SUCCESS;
2945 }
2946
2947 return VOS_STATUS_E_FAILURE;
2948}
2949
2950VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
2951{
2952 hdd_adapter_list_node_t *pHddAdapterNode;
2953 VOS_STATUS status;
2954
2955 ENTER();
2956
2957 do
2958 {
2959 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
2960 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
2961 {
2962 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
2963 vos_mem_free( pHddAdapterNode );
2964 }
2965 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
2966
2967 EXIT();
2968
2969 return VOS_STATUS_SUCCESS;
2970}
2971
2972void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
2973{
2974 v_U8_t addIE[1] = {0};
2975
2976 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2977 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
2978 eANI_BOOLEAN_FALSE) )
2979 {
2980 hddLog(LOGE,
2981 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
2982 }
2983
2984 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2985 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
2986 eANI_BOOLEAN_FALSE) )
2987 {
2988 hddLog(LOGE,
2989 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
2990 }
2991
2992 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2993 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
2994 eANI_BOOLEAN_FALSE) )
2995 {
2996 hddLog(LOGE,
2997 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
2998 }
2999}
3000
3001VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3002{
3003 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3004 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3005 union iwreq_data wrqu;
3006
3007 ENTER();
3008
3009 switch(pAdapter->device_mode)
3010 {
3011 case WLAN_HDD_INFRA_STATION:
3012 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003013 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003014 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3015 {
3016 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3017 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3018 pAdapter->sessionId,
3019 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3020 else
3021 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3022 pAdapter->sessionId,
3023 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3024 //success implies disconnect command got queued up successfully
3025 if(halStatus == eHAL_STATUS_SUCCESS)
3026 {
3027 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3028 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3029 }
3030 memset(&wrqu, '\0', sizeof(wrqu));
3031 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3032 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3033 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3034 }
3035 else
3036 {
3037 hdd_abort_mac_scan(pHddCtx);
3038 }
3039
3040 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3041 {
3042 INIT_COMPLETION(pAdapter->session_close_comp_var);
3043 if (eHAL_STATUS_SUCCESS ==
3044 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3045 hdd_smeCloseSessionCallback, pAdapter))
3046 {
3047 //Block on a completion variable. Can't wait forever though.
3048 wait_for_completion_interruptible_timeout(
3049 &pAdapter->session_close_comp_var,
3050 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3051 }
3052 }
3053
3054 break;
3055
3056 case WLAN_HDD_SOFTAP:
3057 case WLAN_HDD_P2P_GO:
3058 //Any softap specific cleanup here...
3059 mutex_lock(&pHddCtx->sap_lock);
3060 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3061 {
3062 VOS_STATUS status;
3063 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3064
3065 //Stop Bss.
3066 status = WLANSAP_StopBss(pHddCtx->pvosContext);
3067 if (VOS_IS_STATUS_SUCCESS(status))
3068 {
3069 hdd_hostapd_state_t *pHostapdState =
3070 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3071
3072 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
3073
3074 if (!VOS_IS_STATUS_SUCCESS(status))
3075 {
3076 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003077 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003078 }
3079 }
3080 else
3081 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003082 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003083 }
3084 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
3085
3086 if (eHAL_STATUS_FAILURE ==
3087 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
3088 0, NULL, eANI_BOOLEAN_FALSE))
3089 {
3090 hddLog(LOGE,
3091 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003092 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003093 }
3094
3095 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
3096 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
3097 eANI_BOOLEAN_FALSE) )
3098 {
3099 hddLog(LOGE,
3100 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
3101 }
3102
3103 // Reset WNI_CFG_PROBE_RSP Flags
3104 wlan_hdd_reset_prob_rspies(pAdapter);
3105 kfree(pAdapter->sessionCtx.ap.beacon);
3106 pAdapter->sessionCtx.ap.beacon = NULL;
3107 }
3108 mutex_unlock(&pHddCtx->sap_lock);
3109 break;
3110 case WLAN_HDD_MONITOR:
3111 break;
3112 default:
3113 break;
3114 }
3115
3116 EXIT();
3117 return VOS_STATUS_SUCCESS;
3118}
3119
3120VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
3121{
3122 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3123 VOS_STATUS status;
3124 hdd_adapter_t *pAdapter;
3125
3126 ENTER();
3127
3128 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3129
3130 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3131 {
3132 pAdapter = pAdapterNode->pAdapter;
3133 netif_tx_disable(pAdapter->dev);
3134 netif_carrier_off(pAdapter->dev);
3135
3136 hdd_stop_adapter( pHddCtx, pAdapter );
3137
3138 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3139 pAdapterNode = pNext;
3140 }
3141
3142 EXIT();
3143
3144 return VOS_STATUS_SUCCESS;
3145}
3146
3147VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
3148{
3149 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3150 VOS_STATUS status;
3151 hdd_adapter_t *pAdapter;
3152
3153 ENTER();
3154
3155 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3156
3157 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3158 {
3159 pAdapter = pAdapterNode->pAdapter;
3160 netif_tx_disable(pAdapter->dev);
3161 netif_carrier_off(pAdapter->dev);
3162
3163 //Record whether STA is associated
3164 pAdapter->sessionCtx.station.bSendDisconnect =
3165 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
3166 VOS_TRUE : VOS_FALSE;
3167
3168 hdd_deinit_tx_rx(pAdapter);
3169 hdd_wmm_adapter_close(pAdapter);
3170
3171 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3172 pAdapterNode = pNext;
3173 }
3174
3175 EXIT();
3176
3177 return VOS_STATUS_SUCCESS;
3178}
3179
3180VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
3181{
3182 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3183 VOS_STATUS status;
3184 hdd_adapter_t *pAdapter;
3185 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
3186
3187 ENTER();
3188
3189 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3190
3191 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3192 {
3193 pAdapter = pAdapterNode->pAdapter;
3194
3195 switch(pAdapter->device_mode)
3196 {
3197 case WLAN_HDD_INFRA_STATION:
3198 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003199 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003200 hdd_init_station_mode(pAdapter);
3201 /* Open the gates for HDD to receive Wext commands */
3202 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003203 pHddCtx->scan_info.mScanPending = FALSE;
3204 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003205
3206 //Trigger the initial scan
3207 hdd_wlan_initial_scan(pAdapter);
3208
3209 //Indicate disconnect event to supplicant if associated previously
3210 if(pAdapter->sessionCtx.station.bSendDisconnect)
3211 {
3212 union iwreq_data wrqu;
3213 memset(&wrqu, '\0', sizeof(wrqu));
3214 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3215 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3216 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3217 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
3218
Jeff Johnson295189b2012-06-20 16:38:30 -07003219 /* indicate disconnected event to nl80211 */
3220 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
3221 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003222 }
3223 break;
3224
3225 case WLAN_HDD_SOFTAP:
3226 /* softAP can handle SSR */
3227 break;
3228
3229 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003230 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
3231 __func__);
3232 /* event supplicant to restart */
3233 cfg80211_del_sta(pAdapter->dev,
3234 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003235 break;
3236
3237 case WLAN_HDD_MONITOR:
3238 /* monitor interface start */
3239 break;
3240 default:
3241 break;
3242 }
3243
3244 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3245 pAdapterNode = pNext;
3246 }
3247
3248 EXIT();
3249
3250 return VOS_STATUS_SUCCESS;
3251}
3252
3253VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
3254{
3255 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3256 hdd_adapter_t *pAdapter;
3257 VOS_STATUS status;
3258 v_U32_t roamId;
3259
3260 ENTER();
3261
3262 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3263
3264 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3265 {
3266 pAdapter = pAdapterNode->pAdapter;
3267
3268 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3269 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
3270 {
3271 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3272 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3273
3274 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3275 init_completion(&pAdapter->disconnect_comp_var);
3276 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
3277 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3278
3279 wait_for_completion_interruptible_timeout(
3280 &pAdapter->disconnect_comp_var,
3281 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3282
3283 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
3284 pHddCtx->isAmpAllowed = VOS_FALSE;
3285 sme_RoamConnect(pHddCtx->hHal,
3286 pAdapter->sessionId, &(pWextState->roamProfile),
3287 &roamId);
3288 }
3289
3290 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3291 pAdapterNode = pNext;
3292 }
3293
3294 EXIT();
3295
3296 return VOS_STATUS_SUCCESS;
3297}
3298
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07003299void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
3300{
3301 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3302 VOS_STATUS status;
3303 hdd_adapter_t *pAdapter;
3304 hdd_station_ctx_t *pHddStaCtx;
3305 hdd_ap_ctx_t *pHddApCtx;
3306 hdd_hostapd_state_t * pHostapdState;
3307 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
3308 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
3309 const char *p2pMode = "DEV";
3310 const char *ccMode = "Standalone";
3311 int n;
3312
3313 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3314 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3315 {
3316 pAdapter = pAdapterNode->pAdapter;
3317 switch (pAdapter->device_mode) {
3318 case WLAN_HDD_INFRA_STATION:
3319 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3320 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3321 staChannel = pHddStaCtx->conn_info.operationChannel;
3322 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
3323 }
3324 break;
3325 case WLAN_HDD_P2P_CLIENT:
3326 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3327 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3328 p2pChannel = pHddStaCtx->conn_info.operationChannel;
3329 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
3330 p2pMode = "CLI";
3331 }
3332 break;
3333 case WLAN_HDD_P2P_GO:
3334 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3335 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3336 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3337 p2pChannel = pHddApCtx->operatingChannel;
3338 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
3339 }
3340 p2pMode = "GO";
3341 break;
3342 case WLAN_HDD_SOFTAP:
3343 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3344 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3345 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3346 apChannel = pHddApCtx->operatingChannel;
3347 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
3348 }
3349 break;
3350 default:
3351 break;
3352 }
3353 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3354 pAdapterNode = pNext;
3355 }
3356 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
3357 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
3358 }
3359 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
3360 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
3361 if (p2pChannel > 0) {
3362 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
3363 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
3364 }
3365 if (apChannel > 0) {
3366 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
3367 apChannel, MAC_ADDR_ARRAY(apBssid));
3368 }
3369
3370 if (p2pChannel > 0 && apChannel > 0) {
3371 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
3372 }
3373}
3374
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003375bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07003376{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003377 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07003378}
3379
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003380/* Once SSR is disabled then it cannot be set. */
3381void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07003382{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003383 if (HDD_SSR_DISABLED == isSsrRequired)
3384 return;
3385
Jeff Johnson295189b2012-06-20 16:38:30 -07003386 isSsrRequired = value;
3387}
3388
3389VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
3390 hdd_adapter_list_node_t** ppAdapterNode)
3391{
3392 VOS_STATUS status;
3393 spin_lock(&pHddCtx->hddAdapters.lock);
3394 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
3395 (hdd_list_node_t**) ppAdapterNode );
3396 spin_unlock(&pHddCtx->hddAdapters.lock);
3397 return status;
3398}
3399
3400VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
3401 hdd_adapter_list_node_t* pAdapterNode,
3402 hdd_adapter_list_node_t** pNextAdapterNode)
3403{
3404 VOS_STATUS status;
3405 spin_lock(&pHddCtx->hddAdapters.lock);
3406 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
3407 (hdd_list_node_t*) pAdapterNode,
3408 (hdd_list_node_t**)pNextAdapterNode );
3409
3410 spin_unlock(&pHddCtx->hddAdapters.lock);
3411 return status;
3412}
3413
3414VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
3415 hdd_adapter_list_node_t* pAdapterNode)
3416{
3417 VOS_STATUS status;
3418 spin_lock(&pHddCtx->hddAdapters.lock);
3419 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
3420 &pAdapterNode->node );
3421 spin_unlock(&pHddCtx->hddAdapters.lock);
3422 return status;
3423}
3424
3425VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
3426 hdd_adapter_list_node_t** ppAdapterNode)
3427{
3428 VOS_STATUS status;
3429 spin_lock(&pHddCtx->hddAdapters.lock);
3430 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
3431 (hdd_list_node_t**) ppAdapterNode );
3432 spin_unlock(&pHddCtx->hddAdapters.lock);
3433 return status;
3434}
3435
3436VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
3437 hdd_adapter_list_node_t* pAdapterNode)
3438{
3439 VOS_STATUS status;
3440 spin_lock(&pHddCtx->hddAdapters.lock);
3441 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
3442 (hdd_list_node_t*) pAdapterNode );
3443 spin_unlock(&pHddCtx->hddAdapters.lock);
3444 return status;
3445}
3446
3447VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
3448 hdd_adapter_list_node_t* pAdapterNode)
3449{
3450 VOS_STATUS status;
3451 spin_lock(&pHddCtx->hddAdapters.lock);
3452 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
3453 (hdd_list_node_t*) pAdapterNode );
3454 spin_unlock(&pHddCtx->hddAdapters.lock);
3455 return status;
3456}
3457
3458hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
3459 tSirMacAddr macAddr )
3460{
3461 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3462 hdd_adapter_t *pAdapter;
3463 VOS_STATUS status;
3464
3465 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3466
3467 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3468 {
3469 pAdapter = pAdapterNode->pAdapter;
3470
3471 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
3472 macAddr, sizeof(tSirMacAddr) ) )
3473 {
3474 return pAdapter;
3475 }
3476 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3477 pAdapterNode = pNext;
3478 }
3479
3480 return NULL;
3481
3482}
3483
3484hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
3485{
3486 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3487 hdd_adapter_t *pAdapter;
3488 VOS_STATUS status;
3489
3490 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3491
3492 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3493 {
3494 pAdapter = pAdapterNode->pAdapter;
3495
3496 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
3497 IFNAMSIZ ) )
3498 {
3499 return pAdapter;
3500 }
3501 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3502 pAdapterNode = pNext;
3503 }
3504
3505 return NULL;
3506
3507}
3508
3509hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
3510{
3511 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3512 hdd_adapter_t *pAdapter;
3513 VOS_STATUS status;
3514
3515 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3516
3517 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3518 {
3519 pAdapter = pAdapterNode->pAdapter;
3520
3521 if( pAdapter && (mode == pAdapter->device_mode) )
3522 {
3523 return pAdapter;
3524 }
3525 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3526 pAdapterNode = pNext;
3527 }
3528
3529 return NULL;
3530
3531}
3532
3533//Remove this function later
3534hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
3535{
3536 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3537 hdd_adapter_t *pAdapter;
3538 VOS_STATUS status;
3539
3540 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3541
3542 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3543 {
3544 pAdapter = pAdapterNode->pAdapter;
3545
3546 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
3547 {
3548 return pAdapter;
3549 }
3550
3551 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3552 pAdapterNode = pNext;
3553 }
3554
3555 return NULL;
3556
3557}
3558
Jeff Johnson295189b2012-06-20 16:38:30 -07003559/**---------------------------------------------------------------------------
3560
3561 \brief hdd_set_monitor_tx_adapter() -
3562
3563 This API initializes the adapter to be used while transmitting on monitor
3564 adapter.
3565
3566 \param - pHddCtx - Pointer to the HDD context.
3567 pAdapter - Adapter that will used for TX. This can be NULL.
3568 \return - None.
3569 --------------------------------------------------------------------------*/
3570void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3571{
3572 hdd_adapter_t *pMonAdapter;
3573
3574 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
3575
3576 if( NULL != pMonAdapter )
3577 {
3578 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
3579 }
3580}
Jeff Johnson295189b2012-06-20 16:38:30 -07003581/**---------------------------------------------------------------------------
3582
3583 \brief hdd_select_queue() -
3584
3585 This API returns the operating channel of the requested device mode
3586
3587 \param - pHddCtx - Pointer to the HDD context.
3588 - mode - Device mode for which operating channel is required
3589 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
3590 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
3591 \return - channel number. "0" id the requested device is not found OR it is not connected.
3592 --------------------------------------------------------------------------*/
3593v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
3594{
3595 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3596 VOS_STATUS status;
3597 hdd_adapter_t *pAdapter;
3598 v_U8_t operatingChannel = 0;
3599
3600 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3601
3602 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3603 {
3604 pAdapter = pAdapterNode->pAdapter;
3605
3606 if( mode == pAdapter->device_mode )
3607 {
3608 switch(pAdapter->device_mode)
3609 {
3610 case WLAN_HDD_INFRA_STATION:
3611 case WLAN_HDD_P2P_CLIENT:
3612 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3613 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
3614 break;
3615 case WLAN_HDD_SOFTAP:
3616 case WLAN_HDD_P2P_GO:
3617 /*softap connection info */
3618 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3619 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
3620 break;
3621 default:
3622 break;
3623 }
3624
3625 break; //Found the device of interest. break the loop
3626 }
3627
3628 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3629 pAdapterNode = pNext;
3630 }
3631 return operatingChannel;
3632}
3633
3634#ifdef WLAN_FEATURE_PACKET_FILTERING
3635/**---------------------------------------------------------------------------
3636
3637 \brief hdd_set_multicast_list() -
3638
3639 This used to set the multicast address list.
3640
3641 \param - dev - Pointer to the WLAN device.
3642 - skb - Pointer to OS packet (sk_buff).
3643 \return - success/fail
3644
3645 --------------------------------------------------------------------------*/
3646static void hdd_set_multicast_list(struct net_device *dev)
3647{
3648 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07003649 int mc_count;
3650 int i = 0;
3651 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303652
3653 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07003654 {
3655 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303656 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003657 return;
3658 }
3659
3660 if (dev->flags & IFF_ALLMULTI)
3661 {
3662 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003663 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303664 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003665 }
3666 else
3667 {
3668 mc_count = netdev_mc_count(dev);
3669 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003670 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07003671 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
3672 {
3673 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003674 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303675 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003676 return;
3677 }
3678
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303679 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07003680
3681 netdev_for_each_mc_addr(ha, dev) {
3682 if (i == mc_count)
3683 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303684 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
3685 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
3686 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003687 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303688 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07003689 i++;
3690 }
3691 }
3692 return;
3693}
3694#endif
3695
3696/**---------------------------------------------------------------------------
3697
3698 \brief hdd_select_queue() -
3699
3700 This function is registered with the Linux OS for network
3701 core to decide which queue to use first.
3702
3703 \param - dev - Pointer to the WLAN device.
3704 - skb - Pointer to OS packet (sk_buff).
3705 \return - ac, Queue Index/access category corresponding to UP in IP header
3706
3707 --------------------------------------------------------------------------*/
3708v_U16_t hdd_select_queue(struct net_device *dev,
3709 struct sk_buff *skb)
3710{
3711 return hdd_wmm_select_queue(dev, skb);
3712}
3713
3714
3715/**---------------------------------------------------------------------------
3716
3717 \brief hdd_wlan_initial_scan() -
3718
3719 This function triggers the initial scan
3720
3721 \param - pAdapter - Pointer to the HDD adapter.
3722
3723 --------------------------------------------------------------------------*/
3724void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
3725{
3726 tCsrScanRequest scanReq;
3727 tCsrChannelInfo channelInfo;
3728 eHalStatus halStatus;
3729 unsigned long scanId;
3730 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3731
3732 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
3733 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
3734 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
3735
3736 if(sme_Is11dSupported(pHddCtx->hHal))
3737 {
3738 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
3739 if ( HAL_STATUS_SUCCESS( halStatus ) )
3740 {
3741 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
3742 if( !scanReq.ChannelInfo.ChannelList )
3743 {
3744 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
3745 vos_mem_free(channelInfo.ChannelList);
3746 return;
3747 }
3748 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
3749 channelInfo.numOfChannels);
3750 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
3751 vos_mem_free(channelInfo.ChannelList);
3752 }
3753
3754 scanReq.scanType = eSIR_PASSIVE_SCAN;
3755 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
3756 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
3757 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
3758 }
3759 else
3760 {
3761 scanReq.scanType = eSIR_ACTIVE_SCAN;
3762 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
3763 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
3764 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
3765 }
3766
3767 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
3768 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3769 {
3770 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
3771 __func__, halStatus );
3772 }
3773
3774 if(sme_Is11dSupported(pHddCtx->hHal))
3775 vos_mem_free(scanReq.ChannelInfo.ChannelList);
3776}
3777
3778struct fullPowerContext
3779{
3780 struct completion completion;
3781 unsigned int magic;
3782};
3783#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
3784
3785/**---------------------------------------------------------------------------
3786
3787 \brief hdd_full_power_callback() - HDD full power callback function
3788
3789 This is the function invoked by SME to inform the result of a full power
3790 request issued by HDD
3791
3792 \param - callbackcontext - Pointer to cookie
3793 \param - status - result of request
3794
3795 \return - None
3796
3797 --------------------------------------------------------------------------*/
3798static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
3799{
3800 struct fullPowerContext *pContext = callbackContext;
3801
3802 hddLog(VOS_TRACE_LEVEL_INFO,
3803 "%s: context = %p, status = %d", pContext, status);
3804
3805 if (NULL == callbackContext)
3806 {
3807 hddLog(VOS_TRACE_LEVEL_ERROR,
3808 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003809 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07003810 return;
3811 }
3812
3813 /* there is a race condition that exists between this callback function
3814 and the caller since the caller could time out either before or
3815 while this code is executing. we'll assume the timeout hasn't
3816 occurred, but we'll verify that right before we save our work */
3817
3818 if (POWER_CONTEXT_MAGIC != pContext->magic)
3819 {
3820 /* the caller presumably timed out so there is nothing we can do */
3821 hddLog(VOS_TRACE_LEVEL_WARN,
3822 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003823 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07003824 return;
3825 }
3826
3827 /* the race is on. caller could have timed out immediately after
3828 we verified the magic, but if so, caller will wait a short time
3829 for us to notify the caller, so the context will stay valid */
3830 complete(&pContext->completion);
3831}
3832
3833/**---------------------------------------------------------------------------
3834
3835 \brief hdd_wlan_exit() - HDD WLAN exit function
3836
3837 This is the driver exit point (invoked during rmmod)
3838
3839 \param - pHddCtx - Pointer to the HDD Context
3840
3841 \return - None
3842
3843 --------------------------------------------------------------------------*/
3844void hdd_wlan_exit(hdd_context_t *pHddCtx)
3845{
3846 eHalStatus halStatus;
3847 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
3848 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05303849 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003850 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003851 struct fullPowerContext powerContext;
3852 long lrc;
3853
3854 ENTER();
3855
Jeff Johnson88ba7742013-02-27 14:36:02 -08003856 if (VOS_FTM_MODE != hdd_get_conparam())
3857 {
3858 // Unloading, restart logic is no more required.
3859 wlan_hdd_restart_deinit(pHddCtx);
3860 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003861
Jeff Johnson295189b2012-06-20 16:38:30 -07003862 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003863 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003864 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003865 {
3866 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
3867 WLAN_HDD_INFRA_STATION);
3868 if (pAdapter == NULL)
3869 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3870
3871 if (pAdapter != NULL)
3872 {
3873 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
3874 hdd_UnregisterWext(pAdapter->dev);
3875 }
3876 }
3877 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003878
Jeff Johnson295189b2012-06-20 16:38:30 -07003879 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08003880 {
3881 wlan_hdd_ftm_close(pHddCtx);
3882 goto free_hdd_ctx;
3883 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003884 //Stop the Interface TX queue.
3885 //netif_tx_disable(pWlanDev);
3886 //netif_carrier_off(pWlanDev);
3887
Jeff Johnson295189b2012-06-20 16:38:30 -07003888 if (VOS_STA_SAP_MODE == hdd_get_conparam())
3889 {
3890 pAdapter = hdd_get_adapter(pHddCtx,
3891 WLAN_HDD_SOFTAP);
3892 }
3893 else
3894 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003895 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003896 {
3897 pAdapter = hdd_get_adapter(pHddCtx,
3898 WLAN_HDD_INFRA_STATION);
3899 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003900 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003901 /* DeRegister with platform driver as client for Suspend/Resume */
3902 vosStatus = hddDeregisterPmOps(pHddCtx);
3903 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3904 {
3905 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
3906 VOS_ASSERT(0);
3907 }
3908
3909 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
3910 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3911 {
3912 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
3913 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003914
3915 // Cancel any outstanding scan requests. We are about to close all
3916 // of our adapters, but an adapter structure is what SME passes back
3917 // to our callback function. Hence if there are any outstanding scan
3918 // requests then there is a race condition between when the adapter
3919 // is closed and when the callback is invoked. We try to resolve that
3920 // race condition here by canceling any outstanding scans before we
3921 // close the adapters.
3922 // Note that the scans may be cancelled in an asynchronous manner, so
3923 // ideally there needs to be some kind of synchronization. Rather than
3924 // introduce a new synchronization here, we will utilize the fact that
3925 // we are about to Request Full Power, and since that is synchronized,
3926 // the expectation is that by the time Request Full Power has completed,
3927 // all scans will be cancelled.
3928 hdd_abort_mac_scan( pHddCtx );
3929
3930 //Disable IMPS/BMPS as we do not want the device to enter any power
3931 //save mode during shutdown
3932 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3933 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3934 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
3935
3936 //Ensure that device is in full power as we will touch H/W during vos_Stop
3937 init_completion(&powerContext.completion);
3938 powerContext.magic = POWER_CONTEXT_MAGIC;
3939
3940 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
3941 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
3942
3943 if (eHAL_STATUS_SUCCESS != halStatus)
3944 {
3945 if (eHAL_STATUS_PMC_PENDING == halStatus)
3946 {
3947 /* request was sent -- wait for the response */
3948 lrc = wait_for_completion_interruptible_timeout(
3949 &powerContext.completion,
3950 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
3951 /* either we have a response or we timed out
3952 either way, first invalidate our magic */
3953 powerContext.magic = 0;
3954 if (lrc <= 0)
3955 {
3956 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003957 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07003958 /* there is a race condition such that the callback
3959 function could be executing at the same time we are. of
3960 primary concern is if the callback function had already
3961 verified the "magic" but hasn't yet set the completion
3962 variable. Since the completion variable is on our
3963 stack, we'll delay just a bit to make sure the data is
3964 still valid if that is the case */
3965 msleep(50);
3966 }
3967 }
3968 else
3969 {
3970 hddLog(VOS_TRACE_LEVEL_ERROR,
3971 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003972 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07003973 VOS_ASSERT(0);
3974 /* continue -- need to clean up as much as possible */
3975 }
3976 }
3977
3978 // Unregister the Net Device Notifier
3979 unregister_netdevice_notifier(&hdd_netdev_notifier);
3980
Jeff Johnson295189b2012-06-20 16:38:30 -07003981 hdd_stop_all_adapters( pHddCtx );
3982
Jeff Johnson295189b2012-06-20 16:38:30 -07003983#ifdef WLAN_BTAMP_FEATURE
3984 vosStatus = WLANBAP_Stop(pVosContext);
3985 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3986 {
3987 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3988 "%s: Failed to stop BAP",__func__);
3989 }
3990#endif //WLAN_BTAMP_FEATURE
3991
3992 //Stop all the modules
3993 vosStatus = vos_stop( pVosContext );
3994 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3995 {
3996 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3997 "%s: Failed to stop VOSS",__func__);
3998 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3999 }
4000
Jeff Johnson295189b2012-06-20 16:38:30 -07004001 //Assert Deep sleep signal now to put Libra HW in lowest power state
4002 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4003 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4004
4005 //Vote off any PMIC voltage supplies
4006 vos_chipPowerDown(NULL, NULL, NULL);
4007
4008 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4009
4010 //Clean up HDD Nlink Service
4011 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
4012 nl_srv_exit();
4013
4014 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004015 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004016
4017 //Close the scheduler before calling vos_close to make sure no thread is
4018 // scheduled after the each module close is called i.e after all the data
4019 // structures are freed.
4020 vosStatus = vos_sched_close( pVosContext );
4021 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4022 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4023 "%s: Failed to close VOSS Scheduler",__func__);
4024 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4025 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004026#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004027#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4028 /* Destroy the wake lock */
4029 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4030#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004031 /* Destroy the wake lock */
4032 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004033#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004034
4035 //Close VOSS
4036 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4037 vos_close(pVosContext);
4038
Jeff Johnson295189b2012-06-20 16:38:30 -07004039 //Close Watchdog
4040 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4041 vos_watchdog_close(pVosContext);
4042
4043 /* Cancel the vote for XO Core ON.
4044 * This is done here to ensure there is no race condition since MC, TX and WD threads have
4045 * exited at this point
4046 */
4047 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
4048 " when WLAN is turned OFF\n");
4049 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4050 {
4051 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
4052 " Not returning failure."
4053 " Power consumed will be high\n");
4054 }
4055
4056 hdd_close_all_adapters( pHddCtx );
4057
4058
4059 //Free up dynamically allocated members inside HDD Adapter
4060 kfree(pHddCtx->cfg_ini);
4061 pHddCtx->cfg_ini= NULL;
4062
4063 /* free the power on lock from platform driver */
4064 if (free_riva_power_on_lock("wlan"))
4065 {
4066 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
4067 __func__);
4068 }
4069
Jeff Johnson88ba7742013-02-27 14:36:02 -08004070free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08004071 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004072 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004073 if (hdd_is_ssr_required())
4074 {
4075 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07004076 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07004077 msleep(5000);
4078 }
4079 hdd_set_ssr_required (VOS_FALSE);
4080}
4081
4082
4083/**---------------------------------------------------------------------------
4084
4085 \brief hdd_update_config_from_nv() - Function to update the contents of
4086 the running configuration with parameters taken from NV storage
4087
4088 \param - pHddCtx - Pointer to the HDD global context
4089
4090 \return - VOS_STATUS_SUCCESS if successful
4091
4092 --------------------------------------------------------------------------*/
4093static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
4094{
Jeff Johnson295189b2012-06-20 16:38:30 -07004095 v_BOOL_t itemIsValid = VOS_FALSE;
4096 VOS_STATUS status;
4097 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
4098 v_U8_t macLoop;
4099
4100 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
4101 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
4102 if(status != VOS_STATUS_SUCCESS)
4103 {
4104 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
4105 return VOS_STATUS_E_FAILURE;
4106 }
4107
4108 if (itemIsValid == VOS_TRUE)
4109 {
4110 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
4111 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
4112 VOS_MAX_CONCURRENCY_PERSONA);
4113 if(status != VOS_STATUS_SUCCESS)
4114 {
4115 /* Get MAC from NV fail, not update CFG info
4116 * INI MAC value will be used for MAC setting */
4117 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
4118 return VOS_STATUS_E_FAILURE;
4119 }
4120
4121 /* If first MAC is not valid, treat all others are not valid
4122 * Then all MACs will be got from ini file */
4123 if(vos_is_macaddr_zero(&macFromNV[0]))
4124 {
4125 /* MAC address in NV file is not configured yet */
4126 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
4127 return VOS_STATUS_E_INVAL;
4128 }
4129
4130 /* Get MAC address from NV, update CFG info */
4131 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
4132 {
4133 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
4134 {
4135 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
4136 /* This MAC is not valid, skip it
4137 * This MAC will be got from ini file */
4138 }
4139 else
4140 {
4141 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
4142 (v_U8_t *)&macFromNV[macLoop].bytes[0],
4143 VOS_MAC_ADDR_SIZE);
4144 }
4145 }
4146 }
4147 else
4148 {
4149 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
4150 return VOS_STATUS_E_FAILURE;
4151 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004152
Jeff Johnson295189b2012-06-20 16:38:30 -07004153
4154 return VOS_STATUS_SUCCESS;
4155}
4156
4157/**---------------------------------------------------------------------------
4158
4159 \brief hdd_post_voss_start_config() - HDD post voss start config helper
4160
4161 \param - pAdapter - Pointer to the HDD
4162
4163 \return - None
4164
4165 --------------------------------------------------------------------------*/
4166VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
4167{
4168 eHalStatus halStatus;
4169 v_U32_t listenInterval;
4170
Jeff Johnson295189b2012-06-20 16:38:30 -07004171
4172 // Send ready indication to the HDD. This will kick off the MAC
4173 // into a 'running' state and should kick off an initial scan.
4174 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
4175 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4176 {
4177 hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
4178 "code %08d [x%08x]",__func__, halStatus, halStatus );
4179 return VOS_STATUS_E_FAILURE;
4180 }
4181
4182 // Set default LI into HDD context,
4183 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
4184 // And RIVA will crash
4185 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
4186 pHddCtx->hdd_actual_LI_value = listenInterval;
4187
4188 return VOS_STATUS_SUCCESS;
4189}
4190
Jeff Johnson295189b2012-06-20 16:38:30 -07004191/* wake lock APIs for HDD */
4192void hdd_prevent_suspend(void)
4193{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004194#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004195 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004196#else
4197 wcnss_prevent_suspend();
4198#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004199}
4200
4201void hdd_allow_suspend(void)
4202{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004203#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004204 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004205#else
4206 wcnss_allow_suspend();
4207#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004208}
4209
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004210void hdd_allow_suspend_timeout(v_U32_t timeout)
4211{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004212#ifdef WLAN_OPEN_SOURCE
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004213 wake_lock_timeout(&wlan_wake_lock, timeout);
4214#else
4215 /* Do nothing as there is no API in wcnss for timeout*/
4216#endif
4217}
4218
Jeff Johnson295189b2012-06-20 16:38:30 -07004219/**---------------------------------------------------------------------------
4220
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004221 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
4222 information between Host and Riva
4223
4224 This function gets reported version of FW
4225 It also finds the version of Riva headers used to compile the host
4226 It compares the above two and prints a warning if they are different
4227 It gets the SW and HW version string
4228 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
4229 indicating the features they support through a bitmap
4230
4231 \param - pHddCtx - Pointer to HDD context
4232
4233 \return - void
4234
4235 --------------------------------------------------------------------------*/
4236
4237void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
4238{
4239
4240 tSirVersionType versionCompiled;
4241 tSirVersionType versionReported;
4242 tSirVersionString versionString;
4243 tANI_U8 fwFeatCapsMsgSupported = 0;
4244 VOS_STATUS vstatus;
4245
4246 /* retrieve and display WCNSS version information */
4247 do {
4248
4249 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
4250 &versionCompiled);
4251 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4252 {
4253 hddLog(VOS_TRACE_LEVEL_FATAL,
4254 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004255 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004256 break;
4257 }
4258
4259 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
4260 &versionReported);
4261 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4262 {
4263 hddLog(VOS_TRACE_LEVEL_FATAL,
4264 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004265 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004266 break;
4267 }
4268
4269 if ((versionCompiled.major != versionReported.major) ||
4270 (versionCompiled.minor != versionReported.minor) ||
4271 (versionCompiled.version != versionReported.version) ||
4272 (versionCompiled.revision != versionReported.revision))
4273 {
4274 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4275 "Host expected %u.%u.%u.%u\n",
4276 WLAN_MODULE_NAME,
4277 (int)versionReported.major,
4278 (int)versionReported.minor,
4279 (int)versionReported.version,
4280 (int)versionReported.revision,
4281 (int)versionCompiled.major,
4282 (int)versionCompiled.minor,
4283 (int)versionCompiled.version,
4284 (int)versionCompiled.revision);
4285 }
4286 else
4287 {
4288 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4289 WLAN_MODULE_NAME,
4290 (int)versionReported.major,
4291 (int)versionReported.minor,
4292 (int)versionReported.version,
4293 (int)versionReported.revision);
4294 }
4295
4296 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
4297 versionString,
4298 sizeof(versionString));
4299 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4300 {
4301 hddLog(VOS_TRACE_LEVEL_FATAL,
4302 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004303 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004304 break;
4305 }
4306
4307 pr_info("%s: WCNSS software version %s\n",
4308 WLAN_MODULE_NAME, versionString);
4309
4310 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
4311 versionString,
4312 sizeof(versionString));
4313 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4314 {
4315 hddLog(VOS_TRACE_LEVEL_FATAL,
4316 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004317 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004318 break;
4319 }
4320
4321 pr_info("%s: WCNSS hardware version %s\n",
4322 WLAN_MODULE_NAME, versionString);
4323
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004324 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
4325 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004326 send the message only if it the riva is 1.1
4327 minor numbers for different riva branches:
4328 0 -> (1.0)Mainline Build
4329 1 -> (1.1)Mainline Build
4330 2->(1.04) Stability Build
4331 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004332 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004333 ((versionReported.minor>=1) && (versionReported.version>=1)))
4334 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
4335 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004336
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004337 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08004338 {
4339#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4340 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
4341 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
4342#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004343 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08004344 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004345
4346 } while (0);
4347
4348}
4349
4350/**---------------------------------------------------------------------------
4351
Jeff Johnson295189b2012-06-20 16:38:30 -07004352 \brief hdd_wlan_startup() - HDD init function
4353
4354 This is the driver startup code executed once a WLAN device has been detected
4355
4356 \param - dev - Pointer to the underlying device
4357
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004358 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07004359
4360 --------------------------------------------------------------------------*/
4361
4362int hdd_wlan_startup(struct device *dev )
4363{
4364 VOS_STATUS status;
4365 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004366 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004367 hdd_context_t *pHddCtx = NULL;
4368 v_CONTEXT_t pVosContext= NULL;
4369#ifdef WLAN_BTAMP_FEATURE
4370 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
4371 WLANBAP_ConfigType btAmpConfig;
4372 hdd_config_t *pConfig;
4373#endif
4374 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07004375 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004376
4377 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07004378 /*
4379 * cfg80211: wiphy allocation
4380 */
4381 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
4382
4383 if(wiphy == NULL)
4384 {
4385 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004386 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004387 }
4388
4389 pHddCtx = wiphy_priv(wiphy);
4390
Jeff Johnson295189b2012-06-20 16:38:30 -07004391 //Initialize the adapter context to zeros.
4392 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
4393
Jeff Johnson295189b2012-06-20 16:38:30 -07004394 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004395 hdd_prevent_suspend();
4396 pHddCtx->isLoadUnloadInProgress = TRUE;
4397
4398 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4399
4400 /*Get vos context here bcoz vos_open requires it*/
4401 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4402
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08004403 if(pVosContext == NULL)
4404 {
4405 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
4406 goto err_free_hdd_context;
4407 }
4408
Jeff Johnson295189b2012-06-20 16:38:30 -07004409 //Save the Global VOSS context in adapter context for future.
4410 pHddCtx->pvosContext = pVosContext;
4411
4412 //Save the adapter context in global context for future.
4413 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
4414
Jeff Johnson295189b2012-06-20 16:38:30 -07004415 pHddCtx->parent_dev = dev;
4416
4417 init_completion(&pHddCtx->full_pwr_comp_var);
4418 init_completion(&pHddCtx->standby_comp_var);
4419 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004420 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004421 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004422
4423 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
4424
4425 // Load all config first as TL config is needed during vos_open
4426 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
4427 if(pHddCtx->cfg_ini == NULL)
4428 {
4429 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
4430 goto err_free_hdd_context;
4431 }
4432
4433 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
4434
4435 // Read and parse the qcom_cfg.ini file
4436 status = hdd_parse_config_ini( pHddCtx );
4437 if ( VOS_STATUS_SUCCESS != status )
4438 {
4439 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
4440 __func__, WLAN_INI_FILE);
4441 goto err_config;
4442 }
4443
Jeff Johnson295189b2012-06-20 16:38:30 -07004444 /*
4445 * cfg80211: Initialization and registration ...
4446 */
4447 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
4448 {
4449 hddLog(VOS_TRACE_LEVEL_FATAL,
4450 "%s: wlan_hdd_cfg80211_register return failure", __func__);
4451 goto err_wiphy_reg;
4452 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004453
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004454 // Update VOS trace levels based upon the cfg.ini
4455 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
4456 pHddCtx->cfg_ini->vosTraceEnableBAP);
4457 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
4458 pHddCtx->cfg_ini->vosTraceEnableTL);
4459 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
4460 pHddCtx->cfg_ini->vosTraceEnableWDI);
4461 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
4462 pHddCtx->cfg_ini->vosTraceEnableHDD);
4463 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
4464 pHddCtx->cfg_ini->vosTraceEnableSME);
4465 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
4466 pHddCtx->cfg_ini->vosTraceEnablePE);
4467 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
4468 pHddCtx->cfg_ini->vosTraceEnableWDA);
4469 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
4470 pHddCtx->cfg_ini->vosTraceEnableSYS);
4471 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
4472 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004473 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
4474 pHddCtx->cfg_ini->vosTraceEnableSAP);
4475 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
4476 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004477
Jeff Johnson295189b2012-06-20 16:38:30 -07004478 // Update WDI trace levels based upon the cfg.ini
4479 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
4480 pHddCtx->cfg_ini->wdiTraceEnableDAL);
4481 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
4482 pHddCtx->cfg_ini->wdiTraceEnableCTL);
4483 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
4484 pHddCtx->cfg_ini->wdiTraceEnableDAT);
4485 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
4486 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004487
Jeff Johnson88ba7742013-02-27 14:36:02 -08004488 if (VOS_FTM_MODE == hdd_get_conparam())
4489 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004490 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
4491 {
4492 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
4493 goto err_free_hdd_context;
4494 }
4495 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
4496 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08004497 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004498
Jeff Johnson88ba7742013-02-27 14:36:02 -08004499 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07004500 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4501 {
4502 status = vos_watchdog_open(pVosContext,
4503 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
4504
4505 if(!VOS_IS_STATUS_SUCCESS( status ))
4506 {
4507 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004508 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07004509 }
4510 }
4511
4512 pHddCtx->isLogpInProgress = FALSE;
4513 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4514
Jeff Johnson295189b2012-06-20 16:38:30 -07004515 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
4516 if(!VOS_IS_STATUS_SUCCESS(status))
4517 {
4518 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004519 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004520 }
4521
Jeff Johnson295189b2012-06-20 16:38:30 -07004522 status = vos_open( &pVosContext, 0);
4523 if ( !VOS_IS_STATUS_SUCCESS( status ))
4524 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004525 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
4526 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07004527 }
4528
Jeff Johnson295189b2012-06-20 16:38:30 -07004529 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
4530
4531 if ( NULL == pHddCtx->hHal )
4532 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004533 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004534 goto err_vosclose;
4535 }
4536
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004537 status = vos_preStart( pHddCtx->pvosContext );
4538 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4539 {
4540 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
4541 goto err_vosclose;
4542 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004543
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004544 /* Note that the vos_preStart() sequence triggers the cfg download.
4545 The cfg download must occur before we update the SME config
4546 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07004547 status = hdd_set_sme_config( pHddCtx );
4548
4549 if ( VOS_STATUS_SUCCESS != status )
4550 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004551 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
4552 goto err_vosclose;
4553 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004554
4555 //Initialize the WMM module
4556 status = hdd_wmm_init(pHddCtx);
4557 if (!VOS_IS_STATUS_SUCCESS(status))
4558 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004559 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004560 goto err_vosclose;
4561 }
4562
Jeff Johnson295189b2012-06-20 16:38:30 -07004563 /* In the integrated architecture we update the configuration from
4564 the INI file and from NV before vOSS has been started so that
4565 the final contents are available to send down to the cCPU */
4566
4567 // Apply the cfg.ini to cfg.dat
4568 if (FALSE == hdd_update_config_dat(pHddCtx))
4569 {
4570 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
4571 goto err_vosclose;
4572 }
4573
4574 // Apply the NV to cfg.dat
4575 /* Prima Update MAC address only at here */
4576 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
4577 {
4578#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
4579 /* There was not a valid set of MAC Addresses in NV. See if the
4580 default addresses were modified by the cfg.ini settings. If so,
4581 we'll use them, but if not, we'll autogenerate a set of MAC
4582 addresses based upon the device serial number */
4583
4584 static const v_MACADDR_t default_address =
4585 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
4586 unsigned int serialno;
4587 int i;
4588
4589 serialno = wcnss_get_serial_number();
4590 if ((0 != serialno) &&
4591 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
4592 sizeof(default_address))))
4593 {
4594 /* cfg.ini has the default address, invoke autogen logic */
4595
4596 /* MAC address has 3 bytes of OUI so we have a maximum of 3
4597 bytes of the serial number that can be used to generate
4598 the other 3 bytes of the MAC address. Mask off all but
4599 the lower 3 bytes (this will also make sure we don't
4600 overflow in the next step) */
4601 serialno &= 0x00FFFFFF;
4602
4603 /* we need a unique address for each session */
4604 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
4605
4606 /* autogen all addresses */
4607 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4608 {
4609 /* start with the entire default address */
4610 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
4611 /* then replace the lower 3 bytes */
4612 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
4613 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
4614 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
4615
4616 serialno++;
4617 }
4618
4619 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
4620 MAC_ADDRESS_STR,
4621 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4622 }
4623 else
4624#endif //WLAN_AUTOGEN_MACADDR_FEATURE
4625 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004626 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004627 "%s: Invalid MAC address in NV, using MAC from ini file "
4628 MAC_ADDRESS_STR, __func__,
4629 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4630 }
4631 }
4632 {
4633 eHalStatus halStatus;
4634 // Set the MAC Address
4635 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
4636 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
4637 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
4638 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
4639
4640 if (!HAL_STATUS_SUCCESS( halStatus ))
4641 {
4642 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
4643 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08004644 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004645 }
4646 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004647
4648 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
4649 Note: Firmware image will be read and downloaded inside vos_start API */
4650 status = vos_start( pHddCtx->pvosContext );
4651 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4652 {
4653 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
4654 goto err_vosclose;
4655 }
4656
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004657 /* Exchange capability info between Host and FW and also get versioning info from FW */
4658 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004659
4660 status = hdd_post_voss_start_config( pHddCtx );
4661 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4662 {
4663 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
4664 __func__);
4665 goto err_vosstop;
4666 }
4667
Jeff Johnson295189b2012-06-20 16:38:30 -07004668 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4669 {
4670 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
4671 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4672 }
4673 else
4674 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004675 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
4676 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4677 if (pAdapter != NULL)
4678 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304679 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07004680 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304681 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
4682 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
4683 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07004684
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304685 /* Generate the P2P Device Address. This consists of the device's
4686 * primary MAC address with the locally administered bit set.
4687 */
4688 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07004689 }
4690 else
4691 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304692 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
4693 if (p2p_dev_addr != NULL)
4694 {
4695 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
4696 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
4697 }
4698 else
4699 {
4700 hddLog(VOS_TRACE_LEVEL_FATAL,
4701 "%s: Failed to allocate mac_address for p2p_device",
4702 __func__);
4703 goto err_close_adapter;
4704 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004705 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004706
4707 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
4708 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
4709 if ( NULL == pP2pAdapter )
4710 {
4711 hddLog(VOS_TRACE_LEVEL_FATAL,
4712 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004713 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004714 goto err_close_adapter;
4715 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004716 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004717 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004718
4719 if( pAdapter == NULL )
4720 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004721 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
4722 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004723 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004724
Jeff Johnson295189b2012-06-20 16:38:30 -07004725#ifdef WLAN_BTAMP_FEATURE
4726 vStatus = WLANBAP_Open(pVosContext);
4727 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4728 {
4729 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4730 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004731 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004732 }
4733
4734 vStatus = BSL_Init(pVosContext);
4735 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4736 {
4737 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4738 "%s: Failed to Init BSL",__func__);
4739 goto err_bap_close;
4740 }
4741 vStatus = WLANBAP_Start(pVosContext);
4742 if (!VOS_IS_STATUS_SUCCESS(vStatus))
4743 {
4744 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4745 "%s: Failed to start TL",__func__);
4746 goto err_bap_close;
4747 }
4748
4749 pConfig = pHddCtx->cfg_ini;
4750 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
4751 status = WLANBAP_SetConfig(&btAmpConfig);
4752
4753#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07004754
Jeff Johnson295189b2012-06-20 16:38:30 -07004755#ifdef FEATURE_WLAN_SCAN_PNO
4756 /*SME must send channel update configuration to RIVA*/
4757 sme_UpdateChannelConfig(pHddCtx->hHal);
4758#endif
4759
Jeff Johnson295189b2012-06-20 16:38:30 -07004760 /* Register with platform driver as client for Suspend/Resume */
4761 status = hddRegisterPmOps(pHddCtx);
4762 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4763 {
4764 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
4765#ifdef WLAN_BTAMP_FEATURE
4766 goto err_bap_stop;
4767#else
Jeff Johnsone7245742012-09-05 17:12:55 -07004768 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004769#endif //WLAN_BTAMP_FEATURE
4770 }
4771
4772 /* Register TM level change handler function to the platform */
4773 status = hddDevTmRegisterNotifyCallback(pHddCtx);
4774 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4775 {
4776 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
4777 goto err_unregister_pmops;
4778 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004779
4780 /* register for riva power on lock to platform driver */
4781 if (req_riva_power_on_lock("wlan"))
4782 {
4783 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
4784 __func__);
4785 goto err_unregister_pmops;
4786 }
4787
Jeff Johnson295189b2012-06-20 16:38:30 -07004788 // register net device notifier for device change notification
4789 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4790
4791 if(ret < 0)
4792 {
4793 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
4794 goto err_free_power_on_lock;
4795 }
4796
4797 //Initialize the nlink service
4798 if(nl_srv_init() != 0)
4799 {
4800 hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
4801 goto err_reg_netdev;
4802 }
4803
4804 //Initialize the BTC service
4805 if(btc_activate_service(pHddCtx) != 0)
4806 {
4807 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
4808 goto err_nl_srv;
4809 }
4810
4811#ifdef PTT_SOCK_SVC_ENABLE
4812 //Initialize the PTT service
4813 if(ptt_sock_activate_svc(pHddCtx) != 0)
4814 {
4815 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
4816 goto err_nl_srv;
4817 }
4818#endif
4819
Jeff Johnson295189b2012-06-20 16:38:30 -07004820 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004821 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004822 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07004823 /* Action frame registered in one adapter which will
4824 * applicable to all interfaces
4825 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07004826 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07004827 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004828
4829 mutex_init(&pHddCtx->sap_lock);
4830
4831 pHddCtx->isLoadUnloadInProgress = FALSE;
4832
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004833#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004834#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4835 /* Initialize the wake lcok */
4836 wake_lock_init(&pHddCtx->rx_wake_lock,
4837 WAKE_LOCK_SUSPEND,
4838 "qcom_rx_wakelock");
4839#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004840 /* Initialize the wake lcok */
4841 wake_lock_init(&pHddCtx->sap_wake_lock,
4842 WAKE_LOCK_SUSPEND,
4843 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004844#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004845
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004846 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
4847 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07004848
4849 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4850 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004851
4852 // Initialize the restart logic
4853 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05304854
Jeff Johnson295189b2012-06-20 16:38:30 -07004855 goto success;
4856
4857err_nl_srv:
4858 nl_srv_exit();
4859
4860err_reg_netdev:
4861 unregister_netdevice_notifier(&hdd_netdev_notifier);
4862
4863err_free_power_on_lock:
4864 free_riva_power_on_lock("wlan");
4865
4866err_unregister_pmops:
4867 hddDevTmUnregisterNotifyCallback(pHddCtx);
4868 hddDeregisterPmOps(pHddCtx);
4869
4870#ifdef WLAN_BTAMP_FEATURE
4871err_bap_stop:
4872 WLANBAP_Stop(pVosContext);
4873#endif
4874
4875#ifdef WLAN_BTAMP_FEATURE
4876err_bap_close:
4877 WLANBAP_Close(pVosContext);
4878#endif
4879
Jeff Johnson295189b2012-06-20 16:38:30 -07004880err_close_adapter:
4881 hdd_close_all_adapters( pHddCtx );
4882
4883err_vosstop:
4884 vos_stop(pVosContext);
4885
4886err_vosclose:
4887 status = vos_sched_close( pVosContext );
4888 if (!VOS_IS_STATUS_SUCCESS(status)) {
4889 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4890 "%s: Failed to close VOSS Scheduler", __func__);
4891 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
4892 }
4893 vos_close(pVosContext );
4894
Jeff Johnson295189b2012-06-20 16:38:30 -07004895err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004896 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004897
4898err_wdclose:
4899 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4900 vos_watchdog_close(pVosContext);
4901
Jeff Johnson295189b2012-06-20 16:38:30 -07004902err_wiphy_reg:
4903 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004904
4905err_config:
4906 kfree(pHddCtx->cfg_ini);
4907 pHddCtx->cfg_ini= NULL;
4908
4909err_free_hdd_context:
4910 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004911 wiphy_free(wiphy) ;
4912 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004913 VOS_BUG(1);
4914
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08004915 if (hdd_is_ssr_required())
4916 {
4917 /* WDI timeout had happened during load, so SSR is needed here */
4918 subsystem_restart("wcnss");
4919 msleep(5000);
4920 }
4921 hdd_set_ssr_required (VOS_FALSE);
4922
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004923 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004924
4925success:
4926 EXIT();
4927 return 0;
4928}
4929
4930/**---------------------------------------------------------------------------
4931
Jeff Johnson32d95a32012-09-10 13:15:23 -07004932 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07004933
Jeff Johnson32d95a32012-09-10 13:15:23 -07004934 This is the driver entry point - called in different timeline depending
4935 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07004936
4937 \param - None
4938
4939 \return - 0 for success, non zero for failure
4940
4941 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07004942static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004943{
4944 VOS_STATUS status;
4945 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004946 struct device *dev = NULL;
4947 int ret_status = 0;
4948
4949 ENTER();
4950
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004951#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004952 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07004953#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004954
4955 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
4956 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
4957
4958 //Power Up Libra WLAN card first if not already powered up
4959 status = vos_chipPowerUp(NULL,NULL,NULL);
4960 if (!VOS_IS_STATUS_SUCCESS(status))
4961 {
4962 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
4963 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004964 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004965 }
4966
Jeff Johnson295189b2012-06-20 16:38:30 -07004967#ifdef ANI_BUS_TYPE_PCI
4968
4969 dev = wcnss_wlan_get_device();
4970
4971#endif // ANI_BUS_TYPE_PCI
4972
4973#ifdef ANI_BUS_TYPE_PLATFORM
4974 dev = wcnss_wlan_get_device();
4975#endif // ANI_BUS_TYPE_PLATFORM
4976
4977
4978 do {
4979 if (NULL == dev) {
4980 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
4981 ret_status = -1;
4982 break;
4983 }
4984
4985#ifdef MEMORY_DEBUG
4986 vos_mem_init();
4987#endif
4988
4989#ifdef TIMER_MANAGER
4990 vos_timer_manager_init();
4991#endif
4992
4993 /* Preopen VOSS so that it is ready to start at least SAL */
4994 status = vos_preOpen(&pVosContext);
4995
4996 if (!VOS_IS_STATUS_SUCCESS(status))
4997 {
4998 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
4999 ret_status = -1;
5000 break;
5001 }
5002
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005003#ifndef MODULE
5004 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
5005 */
5006 hdd_set_conparam((v_UINT_t)con_mode);
5007#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005008
5009 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005010 if (hdd_wlan_startup(dev))
5011 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005012 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005013 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005014 vos_preClose( &pVosContext );
5015 ret_status = -1;
5016 break;
5017 }
5018
5019 /* Cancel the vote for XO Core ON
5020 * This is done here for safety purposes in case we re-initialize without turning
5021 * it OFF in any error scenario.
5022 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005023 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07005024 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005025 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07005026 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5027 {
5028 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
5029 " Power consumed will be high\n");
5030 }
5031 } while (0);
5032
5033 if (0 != ret_status)
5034 {
5035 //Assert Deep sleep signal now to put Libra HW in lowest power state
5036 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5037 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
5038
5039 //Vote off any PMIC voltage supplies
5040 vos_chipPowerDown(NULL, NULL, NULL);
5041#ifdef TIMER_MANAGER
5042 vos_timer_exit();
5043#endif
5044#ifdef MEMORY_DEBUG
5045 vos_mem_exit();
5046#endif
5047
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005048#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005049 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005050#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005051 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
5052 }
5053 else
5054 {
5055 //Send WLAN UP indication to Nlink Service
5056 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
5057
5058 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
5059
5060 }
5061
5062 EXIT();
5063
5064 return ret_status;
5065}
5066
Jeff Johnson32d95a32012-09-10 13:15:23 -07005067/**---------------------------------------------------------------------------
5068
5069 \brief hdd_module_init() - Init Function
5070
5071 This is the driver entry point (invoked when module is loaded using insmod)
5072
5073 \param - None
5074
5075 \return - 0 for success, non zero for failure
5076
5077 --------------------------------------------------------------------------*/
5078#ifdef MODULE
5079static int __init hdd_module_init ( void)
5080{
5081 return hdd_driver_init();
5082}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005083#else /* #ifdef MODULE */
5084static int __init hdd_module_init ( void)
5085{
5086 /* Driver initialization is delayed to fwpath_changed_handler */
5087 return 0;
5088}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005089#endif /* #ifdef MODULE */
5090
Jeff Johnson295189b2012-06-20 16:38:30 -07005091
5092/**---------------------------------------------------------------------------
5093
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005094 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005095
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005096 This is the driver exit point (invoked when module is unloaded using rmmod
5097 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07005098
5099 \param - None
5100
5101 \return - None
5102
5103 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005104static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005105{
5106 hdd_context_t *pHddCtx = NULL;
5107 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005108
5109 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
5110
5111 //Get the global vos context
5112 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5113
5114 if(!pVosContext)
5115 {
5116 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
5117 goto done;
5118 }
5119
5120 //Get the HDD context.
5121 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
5122
5123 if(!pHddCtx)
5124 {
5125 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
5126 }
5127 else
5128 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005129 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07005130 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07005131 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
5132 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07005133 }
5134
5135 pHddCtx->isLoadUnloadInProgress = TRUE;
5136 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5137
5138 //Do all the cleanup before deregistering the driver
5139 hdd_wlan_exit(pHddCtx);
5140 }
5141
Jeff Johnson295189b2012-06-20 16:38:30 -07005142 vos_preClose( &pVosContext );
5143
5144#ifdef TIMER_MANAGER
5145 vos_timer_exit();
5146#endif
5147#ifdef MEMORY_DEBUG
5148 vos_mem_exit();
5149#endif
5150
5151done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005152#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005153 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005154#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005155 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
5156}
5157
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005158/**---------------------------------------------------------------------------
5159
5160 \brief hdd_module_exit() - Exit function
5161
5162 This is the driver exit point (invoked when module is unloaded using rmmod)
5163
5164 \param - None
5165
5166 \return - None
5167
5168 --------------------------------------------------------------------------*/
5169static void __exit hdd_module_exit(void)
5170{
5171 hdd_driver_exit();
5172}
5173
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005174#ifdef MODULE
5175static int fwpath_changed_handler(const char *kmessage,
5176 struct kernel_param *kp)
5177{
5178 /* nothing to do when driver is DLKM */
5179 return 0;
5180}
5181
5182static int con_mode_handler(const char *kmessage,
5183 struct kernel_param *kp)
5184{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07005185 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005186}
5187#else /* #ifdef MODULE */
5188/**---------------------------------------------------------------------------
5189
5190 \brief fwpath_changed_handler() - Handler Function
5191
5192 This is the driver entry point
5193 - delayed driver initialization when driver is statically linked
5194 - invoked when module parameter fwpath is modified from userpspace to signal
5195 initializing the WLAN driver
5196
5197 \return - 0 for success, non zero for failure
5198
5199 --------------------------------------------------------------------------*/
5200static int fwpath_changed_handler(const char *kmessage,
5201 struct kernel_param *kp)
5202{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005203 int ret_status;
5204
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005205 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005206 ret_status = hdd_driver_init();
5207 wlan_hdd_inited = ret_status ? 0 : 1;
5208 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005209 }
5210
5211 hdd_driver_exit();
5212
5213 msleep(200);
5214
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005215 ret_status = hdd_driver_init();
5216 wlan_hdd_inited = ret_status ? 0 : 1;
5217 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005218}
5219
Jeff Johnson295189b2012-06-20 16:38:30 -07005220/**---------------------------------------------------------------------------
5221
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005222 \brief con_mode_handler() -
5223
5224 Handler function for module param con_mode when it is changed by userspace
5225 Dynamically linked - do nothing
5226 Statically linked - exit and init driver, as in rmmod and insmod
5227
5228 \param -
5229
5230 \return -
5231
5232 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005233static int con_mode_handler(const char *kmessage,
5234 struct kernel_param *kp)
5235{
5236 int ret = param_set_int(kmessage, kp);
5237
5238 if (ret)
5239 return ret;
5240
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005241 return fwpath_changed_handler(kmessage, kp);
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005242}
5243#endif /* #ifdef MODULE */
5244
5245/**---------------------------------------------------------------------------
5246
Jeff Johnson295189b2012-06-20 16:38:30 -07005247 \brief hdd_get_conparam() -
5248
5249 This is the driver exit point (invoked when module is unloaded using rmmod)
5250
5251 \param - None
5252
5253 \return - tVOS_CON_MODE
5254
5255 --------------------------------------------------------------------------*/
5256tVOS_CON_MODE hdd_get_conparam ( void )
5257{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005258#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07005259 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005260#else
5261 return (tVOS_CON_MODE)curr_con_mode;
5262#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005263}
5264void hdd_set_conparam ( v_UINT_t newParam )
5265{
5266 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005267#ifndef MODULE
5268 curr_con_mode = con_mode;
5269#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005270}
5271/**---------------------------------------------------------------------------
5272
5273 \brief hdd_softap_sta_deauth() - function
5274
5275 This to take counter measure to handle deauth req from HDD
5276
5277 \param - pAdapter - Pointer to the HDD
5278
5279 \param - enable - boolean value
5280
5281 \return - None
5282
5283 --------------------------------------------------------------------------*/
5284
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005285VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07005286{
Jeff Johnson295189b2012-06-20 16:38:30 -07005287 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005288 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07005289
5290 ENTER();
5291
5292 hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5293
5294 //Ignore request to deauth bcmc station
5295 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005296 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005297
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005298 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07005299
5300 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005301 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005302}
5303
5304/**---------------------------------------------------------------------------
5305
5306 \brief hdd_softap_sta_disassoc() - function
5307
5308 This to take counter measure to handle deauth req from HDD
5309
5310 \param - pAdapter - Pointer to the HDD
5311
5312 \param - enable - boolean value
5313
5314 \return - None
5315
5316 --------------------------------------------------------------------------*/
5317
5318void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
5319{
5320 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5321
5322 ENTER();
5323
5324 hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5325
5326 //Ignore request to disassoc bcmc station
5327 if( pDestMacAddress[0] & 0x1 )
5328 return;
5329
5330 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
5331}
5332
5333void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
5334{
5335 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5336
5337 ENTER();
5338
5339 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5340
5341 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
5342}
5343
Jeff Johnson295189b2012-06-20 16:38:30 -07005344/**---------------------------------------------------------------------------
5345 *
5346 * \brief hdd_get__concurrency_mode() -
5347 *
5348 *
5349 * \param - None
5350 *
5351 * \return - CONCURRENCY MODE
5352 *
5353 * --------------------------------------------------------------------------*/
5354tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
5355{
5356 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5357 hdd_context_t *pHddCtx;
5358
5359 if (NULL != pVosContext)
5360 {
5361 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5362 if (NULL != pHddCtx)
5363 {
5364 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
5365 }
5366 }
5367
5368 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005369 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005370 return VOS_STA;
5371}
5372
5373/* Decide whether to allow/not the apps power collapse.
5374 * Allow apps power collapse if we are in connected state.
5375 * if not, allow only if we are in IMPS */
5376v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
5377{
5378 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08005379 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005380 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07005381 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5382 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5383 hdd_adapter_t *pAdapter = NULL;
5384 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08005385 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005386
Jeff Johnson295189b2012-06-20 16:38:30 -07005387 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5388 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005389
Yathish9f22e662012-12-10 14:21:35 -08005390 concurrent_state = hdd_get_concurrency_mode();
5391
5392#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5393 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
5394 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
5395 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
5396 return TRUE;
5397#endif
5398
Jeff Johnson295189b2012-06-20 16:38:30 -07005399 /*loop through all adapters. TBD fix for Concurrency */
5400 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5401 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5402 {
5403 pAdapter = pAdapterNode->pAdapter;
5404 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
5405 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5406 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005407 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07005408 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08005409 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005410 (eANI_BOOLEAN_TRUE == scanRspPending) ||
5411 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07005412 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005413 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005414 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
5415 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07005416 return FALSE;
5417 }
5418 }
5419 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5420 pAdapterNode = pNext;
5421 }
5422 return TRUE;
5423}
5424
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08005425/* Decides whether to send suspend notification to Riva
5426 * if any adapter is in BMPS; then it is required */
5427v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
5428{
5429 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
5430 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5431
5432 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
5433 {
5434 return TRUE;
5435 }
5436 return FALSE;
5437}
5438
Jeff Johnson295189b2012-06-20 16:38:30 -07005439void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5440{
5441 switch(mode)
5442 {
5443 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005444 case WLAN_HDD_P2P_CLIENT:
5445 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005446 case WLAN_HDD_SOFTAP:
Jeff Johnsone7245742012-09-05 17:12:55 -07005447 pHddCtx->concurrency_mode |= (1 << mode);
5448 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07005449 break;
5450 default:
5451 break;
5452
5453 }
5454 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5455 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5456}
5457
5458
5459void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5460{
5461 switch(mode)
5462 {
5463 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005464 case WLAN_HDD_P2P_CLIENT:
5465 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005466 case WLAN_HDD_SOFTAP:
5467 pHddCtx->no_of_sessions[mode]--;
5468 if (!(pHddCtx->no_of_sessions[mode]))
5469 pHddCtx->concurrency_mode &= (~(1 << mode));
5470 break;
5471 default:
5472 break;
5473 }
5474 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5475 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5476}
5477
Jeff Johnsone7245742012-09-05 17:12:55 -07005478/**---------------------------------------------------------------------------
5479 *
5480 * \brief wlan_hdd_restart_init
5481 *
5482 * This function initalizes restart timer/flag. An internal function.
5483 *
5484 * \param - pHddCtx
5485 *
5486 * \return - None
5487 *
5488 * --------------------------------------------------------------------------*/
5489
5490static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
5491{
5492 /* Initialize */
5493 pHddCtx->hdd_restart_retries = 0;
5494 atomic_set(&pHddCtx->isRestartInProgress, 0);
5495 vos_timer_init(&pHddCtx->hdd_restart_timer,
5496 VOS_TIMER_TYPE_SW,
5497 wlan_hdd_restart_timer_cb,
5498 pHddCtx);
5499}
5500/**---------------------------------------------------------------------------
5501 *
5502 * \brief wlan_hdd_restart_deinit
5503 *
5504 * This function cleans up the resources used. An internal function.
5505 *
5506 * \param - pHddCtx
5507 *
5508 * \return - None
5509 *
5510 * --------------------------------------------------------------------------*/
5511
5512static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
5513{
5514
5515 VOS_STATUS vos_status;
5516 /* Block any further calls */
5517 atomic_set(&pHddCtx->isRestartInProgress, 1);
5518 /* Cleanup */
5519 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
5520 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005521 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005522 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
5523 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005524 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005525
5526}
5527
5528/**---------------------------------------------------------------------------
5529 *
5530 * \brief wlan_hdd_framework_restart
5531 *
5532 * This function uses a cfg80211 API to start a framework initiated WLAN
5533 * driver module unload/load.
5534 *
5535 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
5536 *
5537 *
5538 * \param - pHddCtx
5539 *
5540 * \return - VOS_STATUS_SUCCESS: Success
5541 * VOS_STATUS_E_EMPTY: Adapter is Empty
5542 * VOS_STATUS_E_NOMEM: No memory
5543
5544 * --------------------------------------------------------------------------*/
5545
5546static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
5547{
5548 VOS_STATUS status = VOS_STATUS_SUCCESS;
5549 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5550 int len = (sizeof (struct ieee80211_mgmt));
5551 struct ieee80211_mgmt *mgmt = NULL;
5552
5553 /* Prepare the DEAUTH managment frame with reason code */
5554 mgmt = kzalloc(len, GFP_KERNEL);
5555 if(mgmt == NULL)
5556 {
5557 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1250df42012-12-10 14:31:52 -08005558 "%s: memory allocation failed (%d bytes)", __func__, len);
Jeff Johnsone7245742012-09-05 17:12:55 -07005559 return VOS_STATUS_E_NOMEM;
5560 }
5561 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
5562
5563 /* Iterate over all adapters/devices */
5564 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5565 do
5566 {
5567 if( (status == VOS_STATUS_SUCCESS) &&
5568 pAdapterNode &&
5569 pAdapterNode->pAdapter)
5570 {
5571 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5572 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
5573 pAdapterNode->pAdapter->dev->name,
5574 pAdapterNode->pAdapter->device_mode,
5575 pHddCtx->hdd_restart_retries + 1);
5576 /*
5577 * CFG80211 event to restart the driver
5578 *
5579 * 'cfg80211_send_unprot_deauth' sends a
5580 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
5581 * of SME(Linux Kernel) state machine.
5582 *
5583 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
5584 * the driver.
5585 *
5586 */
5587
5588 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
5589 }
5590 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5591 pAdapterNode = pNext;
5592 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
5593
5594
5595 /* Free the allocated management frame */
5596 kfree(mgmt);
5597
5598 /* Retry until we unload or reach max count */
5599 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
5600 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
5601
5602 return status;
5603
5604}
5605/**---------------------------------------------------------------------------
5606 *
5607 * \brief wlan_hdd_restart_timer_cb
5608 *
5609 * Restart timer callback. An internal function.
5610 *
5611 * \param - User data:
5612 *
5613 * \return - None
5614 *
5615 * --------------------------------------------------------------------------*/
5616
5617void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
5618{
5619 hdd_context_t *pHddCtx = usrDataForCallback;
5620 wlan_hdd_framework_restart(pHddCtx);
5621 return;
5622
5623}
5624
5625
5626/**---------------------------------------------------------------------------
5627 *
5628 * \brief wlan_hdd_restart_driver
5629 *
5630 * This function sends an event to supplicant to restart the WLAN driver.
5631 *
5632 * This function is called from vos_wlanRestart.
5633 *
5634 * \param - pHddCtx
5635 *
5636 * \return - VOS_STATUS_SUCCESS: Success
5637 * VOS_STATUS_E_EMPTY: Adapter is Empty
5638 * VOS_STATUS_E_ALREADY: Request already in progress
5639
5640 * --------------------------------------------------------------------------*/
5641VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
5642{
5643 VOS_STATUS status = VOS_STATUS_SUCCESS;
5644
5645 /* A tight check to make sure reentrancy */
5646 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
5647 {
5648 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
5649 "%s: WLAN restart is already in progress", __func__);
5650
5651 return VOS_STATUS_E_ALREADY;
5652 }
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005653 /* when WLAN driver is statically linked, then invoke SSR by sending
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005654 * the reset interrupt. If it is DLKM, then use restart API
5655 */
5656#ifdef MODULE
Jeff Johnsone7245742012-09-05 17:12:55 -07005657 status = wlan_hdd_framework_restart(pHddCtx);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005658#else
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005659#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005660 wcnss_reset_intr();
5661#endif
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005662#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005663
Jeff Johnsone7245742012-09-05 17:12:55 -07005664 return status;
5665}
5666
5667
Jeff Johnson295189b2012-06-20 16:38:30 -07005668//Register the module init/exit functions
5669module_init(hdd_module_init);
5670module_exit(hdd_module_exit);
5671
5672MODULE_LICENSE("Dual BSD/GPL");
5673MODULE_AUTHOR("Qualcomm Atheros, Inc.");
5674MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
5675
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005676module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
5677 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07005678
5679module_param_call(fwpath, fwpath_changed_handler, param_get_string, fwpath,
5680 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);