blob: 89fa9caac35bbbedd12aee88c8ca99ecb6ea505a [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
Jeff Johnson76052702013-04-16 13:55:05 -0700147static char fwpath_buffer[BUF_LEN];
148static struct kparam_string fwpath = {
149 .string = fwpath_buffer,
150 .maxlen = BUF_LEN,
151};
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700152#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700153static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700154#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700155
Jeff Johnsone7245742012-09-05 17:12:55 -0700156/*
157 * The rate at which the driver sends RESTART event to supplicant
158 * once the function 'vos_wlanRestart()' is called
159 *
160 */
161#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
162#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800163#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700164static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700165#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700166/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700167static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700168
169//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700170static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
171static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
172static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
173void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800174void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700175
Jeff Johnson295189b2012-06-20 16:38:30 -0700176v_U16_t hdd_select_queue(struct net_device *dev,
177 struct sk_buff *skb);
178
179#ifdef WLAN_FEATURE_PACKET_FILTERING
180static void hdd_set_multicast_list(struct net_device *dev);
181#endif
182
183void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700184int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700185
186extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800187#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
188void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
189static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
190static VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700191static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
192 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
193 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800194#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700195static int hdd_netdev_notifier_call(struct notifier_block * nb,
196 unsigned long state,
197 void *ndev)
198{
199 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700200 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700201 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700202#ifdef WLAN_BTAMP_FEATURE
203 VOS_STATUS status;
204 hdd_context_t *pHddCtx;
205#endif
206
207 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700208 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700209 (strncmp(dev->name, "p2p", 3)))
210 return NOTIFY_DONE;
211
212 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700213 return NOTIFY_DONE;
214
Jeff Johnson295189b2012-06-20 16:38:30 -0700215 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700216 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700217
Jeff Johnson27cee452013-03-27 11:10:24 -0700218 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700219 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800220 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700221 VOS_ASSERT(0);
222 return NOTIFY_DONE;
223 }
224
Jeff Johnson27cee452013-03-27 11:10:24 -0700225 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
226 if (NULL == pHddCtx)
227 {
228 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
229 VOS_ASSERT(0);
230 return NOTIFY_DONE;
231 }
232
233 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
234 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700235
236 switch (state) {
237 case NETDEV_REGISTER:
238 break;
239
240 case NETDEV_UNREGISTER:
241 break;
242
243 case NETDEV_UP:
244 break;
245
246 case NETDEV_DOWN:
247 break;
248
249 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700250 if(TRUE == pAdapter->isLinkUpSvcNeeded)
251 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700252 break;
253
254 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700255 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700256 {
257 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800258 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700259 hdd_abort_mac_scan(pAdapter->pHddCtx);
260 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800261 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700262 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
263 if(!result)
264 {
265 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800266 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700267 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700268 }
269 }
270 else
271 {
272 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700273 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700274 }
275#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700276 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700277 status = WLANBAP_StopAmp();
278 if(VOS_STATUS_SUCCESS != status )
279 {
280 pHddCtx->isAmpAllowed = VOS_TRUE;
281 hddLog(VOS_TRACE_LEVEL_FATAL,
282 "%s: Failed to stop AMP", __func__);
283 }
284 else
285 {
286 //a state m/c implementation in PAL is TBD to avoid this delay
287 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700288 if ( pHddCtx->isAmpAllowed )
289 {
290 WLANBAP_DeregisterFromHCI();
291 pHddCtx->isAmpAllowed = VOS_FALSE;
292 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700293 }
294#endif //WLAN_BTAMP_FEATURE
295 break;
296
297 default:
298 break;
299 }
300
301 return NOTIFY_DONE;
302}
303
304struct notifier_block hdd_netdev_notifier = {
305 .notifier_call = hdd_netdev_notifier_call,
306};
307
308/*---------------------------------------------------------------------------
309 * Function definitions
310 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700311void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
312void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700313//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700314static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700315#ifndef MODULE
316/* current con_mode - used only for statically linked driver
317 * con_mode is changed by userspace to indicate a mode change which will
318 * result in calling the module exit and init functions. The module
319 * exit function will clean up based on the value of con_mode prior to it
320 * being changed by userspace. So curr_con_mode records the current con_mode
321 * for exit when con_mode becomes the next mode for init
322 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700323static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700324#endif
325
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800326/**---------------------------------------------------------------------------
327
328 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
329
330 Called immediately after the cfg.ini is read in order to configure
331 the desired trace levels.
332
333 \param - moduleId - module whose trace level is being configured
334 \param - bitmask - bitmask of log levels to be enabled
335
336 \return - void
337
338 --------------------------------------------------------------------------*/
339static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
340{
341 wpt_tracelevel level;
342
343 /* if the bitmask is the default value, then a bitmask was not
344 specified in cfg.ini, so leave the logging level alone (it
345 will remain at the "compiled in" default value) */
346 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
347 {
348 return;
349 }
350
351 /* a mask was specified. start by disabling all logging */
352 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
353
354 /* now cycle through the bitmask until all "set" bits are serviced */
355 level = VOS_TRACE_LEVEL_FATAL;
356 while (0 != bitmask)
357 {
358 if (bitmask & 1)
359 {
360 vos_trace_setValue(moduleId, level, 1);
361 }
362 level++;
363 bitmask >>= 1;
364 }
365}
366
367
Jeff Johnson295189b2012-06-20 16:38:30 -0700368/**---------------------------------------------------------------------------
369
370 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
371
372 Called immediately after the cfg.ini is read in order to configure
373 the desired trace levels in the WDI.
374
375 \param - moduleId - module whose trace level is being configured
376 \param - bitmask - bitmask of log levels to be enabled
377
378 \return - void
379
380 --------------------------------------------------------------------------*/
381static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
382{
383 wpt_tracelevel level;
384
385 /* if the bitmask is the default value, then a bitmask was not
386 specified in cfg.ini, so leave the logging level alone (it
387 will remain at the "compiled in" default value) */
388 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
389 {
390 return;
391 }
392
393 /* a mask was specified. start by disabling all logging */
394 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
395
396 /* now cycle through the bitmask until all "set" bits are serviced */
397 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
398 while (0 != bitmask)
399 {
400 if (bitmask & 1)
401 {
402 wpalTraceSetLevel(moduleId, level, 1);
403 }
404 level++;
405 bitmask >>= 1;
406 }
407}
Jeff Johnson295189b2012-06-20 16:38:30 -0700408
409int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
410{
411 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
412 hdd_priv_data_t priv_data;
413 tANI_U8 *command = NULL;
414 int ret = 0;
415
416 if (NULL == pAdapter)
417 {
418 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700419 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700420 ret = -ENODEV;
421 goto exit;
422 }
423
Jeff Johnsone7245742012-09-05 17:12:55 -0700424 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700425 {
426 ret = -EINVAL;
427 goto exit;
428 }
429
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -0700430 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
431 {
432 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
433 "%s:LOGP in Progress. Ignore!!!", __func__);
434 ret = -EBUSY;
435 goto exit;
436 }
437
Jeff Johnson295189b2012-06-20 16:38:30 -0700438 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
439 {
440 ret = -EFAULT;
441 goto exit;
442 }
443
444 command = kmalloc(priv_data.total_len, GFP_KERNEL);
445 if (!command)
446 {
447 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700448 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700449 ret = -ENOMEM;
450 goto exit;
451 }
452
453 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
454 {
455 ret = -EFAULT;
456 goto exit;
457 }
458
459 if ((SIOCDEVPRIVATE + 1) == cmd)
460 {
461 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
462
463 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700464 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700465
466 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
467 {
468 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
469 sizeof(tSirMacAddr)))
470 {
471 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700472 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700473 ret = -EFAULT;
474 }
475 }
Amar Singhal0974e402013-02-12 14:27:46 -0800476 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700477 {
Amar Singhal0974e402013-02-12 14:27:46 -0800478 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700479 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800480
Jeff Johnson295189b2012-06-20 16:38:30 -0700481 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800482
483 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700484 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700485 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800486 "%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 -0700487 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800488 ret = hdd_setBand_helper(dev, ptr);
489 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700490 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
491 {
492 char *country_code;
493
494 country_code = command + 8;
495 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
496 pAdapter, pHddCtx->pvosContext);
497 if( 0 != ret )
498 {
499 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
500 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
501
502 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700503 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800504#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
505 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
506 {
507 tANI_U8 *value = command;
508 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
509 tANI_U8 revision = 0;
510 eHalStatus status = eHAL_STATUS_SUCCESS;
511 v_REGDOMAIN_t regId;
512
513 status = hdd_parse_countryrev(value, countryCode, &revision);
514 if (eHAL_STATUS_SUCCESS != status)
515 {
516 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
517 "%s: Failed to parse country revision information", __func__);
518 ret = -EINVAL;
519 goto exit;
520 }
521
522 /* Validate country code */
523 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
524 if (eHAL_STATUS_SUCCESS != status)
525 {
526 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
527 "%s: Invalid country code %s", __func__, countryCode);
528 ret = -EINVAL;
529 goto exit;
530 }
531
532 /* Validate revision */
533 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
534 {
535 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
536 "%s: Invalid revision %d", __func__, revision);
537 ret = -EINVAL;
538 goto exit;
539 }
540
541 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
542 pAdapter, pHddCtx->pvosContext);
543 if (0 != ret)
544 {
545 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
546 "%s: SME Change Country code fail ret=%d", __func__, ret);
547 ret = -EINVAL;
548 goto exit;
549 }
550
551 if (0 == strncmp(countryCode, "KR", 2))
552 {
553 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
554 revision);
555 if (eHAL_STATUS_SUCCESS != status)
556 {
557 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
558 "%s: Failed to build valid channel list", __func__);
559 ret = -EINVAL;
560 goto exit;
561 }
562 }
563 }
564#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700565 /*
566 command should be a string having format
567 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
568 */
Amar Singhal0974e402013-02-12 14:27:46 -0800569 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700570 {
Amar Singhal0974e402013-02-12 14:27:46 -0800571 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700572
573 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700574 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700575
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800576 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700577 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800578 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
579 {
580 int suspend = 0;
581 tANI_U8 *ptr = (tANI_U8*)command + 15;
582
583 suspend = *ptr - '0';
584 hdd_set_wlan_suspend_mode(suspend);
585 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800586#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
587 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
588 {
589 tANI_U8 *value = command;
590 int rssi = 0;
591 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
592 eHalStatus status = eHAL_STATUS_SUCCESS;
593
594 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
595 value = value + 15;
596
597 sscanf(value, "%d", &rssi);
598 lookUpThreshold = abs(rssi);
599 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
600 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
601 {
602 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
603 "Neighbor lookup threshold value %d is out of range"
604 " (Min: %d Max: %d)", lookUpThreshold,
605 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
606 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
607 ret = -EINVAL;
608 goto exit;
609 }
610
611 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
612 "%s: Received Command to Set Roam trigger"
613 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
614
615 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
616 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
617 if (eHAL_STATUS_SUCCESS != status)
618 {
619 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
620 "%s: Failed to set roam trigger, try again", __func__);
621 ret = -EPERM;
622 goto exit;
623 }
624
625 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
626 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
627 }
628 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
629 {
630 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
631 int rssi = (-1) * lookUpThreshold;
632 char extra[32];
633 tANI_U8 len = 0;
634
635 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
636 if (copy_to_user(priv_data.buf, &extra, len + 1))
637 {
638 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
639 "%s: failed to copy data to user buffer", __func__);
640 ret = -EFAULT;
641 goto exit;
642 }
643 }
644 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
645 {
646 tANI_U8 *value = command;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700647 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800648 /* input refresh period is in terms of seconds */
649 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
650 value = value + 18;
651 /* Convert the value from ascii to integer */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700652 ret = kstrtou16(value, 10, &neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800653 if (ret < 0)
654 {
655 /* If the input value is greater than max value of datatype, then also
656 kstrtou16 fails */
657 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
658 "%s: kstrtou16 failed ",
659 "Input value may be out of range[%d - %d]",
660 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700661 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
662 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800663 ret = -EINVAL;
664 goto exit;
665 }
666
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700667 neighborEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod * 1000;
668 if ((neighborEmptyScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
669 (neighborEmptyScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800670 {
671 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700672 "Neighbor empty scan results refresh period value %d is out of range"
673 " (Min: %d Max: %d)", neighborEmptyScanRefreshPeriod/1000,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700674 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
675 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800676 ret = -EINVAL;
677 goto exit;
678 }
679
680 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
681 "%s: Received Command to Set roam scan period"
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700682 " (Empty Scan refresh period) = %d", __func__, neighborEmptyScanRefreshPeriod/1000);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800683
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700684 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
685 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800686 }
687 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
688 {
689 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
690 char extra[32];
691 tANI_U8 len = 0;
692
693 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
694 /* Returned value is in units of seconds */
695 if (copy_to_user(priv_data.buf, &extra, len + 1))
696 {
697 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
698 "%s: failed to copy data to user buffer", __func__);
699 ret = -EFAULT;
700 goto exit;
701 }
702 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700703 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
704 {
705 tANI_U8 *value = command;
706 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
707 /* input refresh period is in terms of seconds */
708 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
709 value = value + 25;
710 /* Convert the value from ascii to integer */
711 ret = kstrtou16(value, 10, &neighborScanRefreshPeriod);
712 if (ret < 0)
713 {
714 /* If the input value is greater than max value of datatype, then also
715 kstrtou16 fails */
716 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
717 "%s: kstrtou16 failed ",
718 "Input value may be out of range[%d - %d]",
719 __func__,
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700720 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
721 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700722 ret = -EINVAL;
723 goto exit;
724 }
725
726 neighborScanRefreshPeriod = neighborScanRefreshPeriod * 1000;
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700727 if ((neighborScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
728 (neighborScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700729 {
730 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
731 "Neighbor scan results refresh period value %d is out of range"
732 " (Min: %d Max: %d)", neighborScanRefreshPeriod/1000,
733 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
734 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
735 ret = -EINVAL;
736 goto exit;
737 }
738
739 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
740 "%s: Received Command to Set roam scan refresh period"
741 " (Scan refresh period) = %d", __func__, neighborScanRefreshPeriod/1000);
742
743 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
744 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
745 }
746 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
747 {
748 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
749 char extra[32];
750 tANI_U8 len = 0;
751
752 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
753 /* Returned value is in units of seconds */
754 if (copy_to_user(priv_data.buf, &extra, len + 1))
755 {
756 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
757 "%s: failed to copy data to user buffer", __func__);
758 ret = -EFAULT;
759 goto exit;
760 }
761 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800762#endif
763#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
764 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
765 {
766 tANI_U8 *value = command;
767 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
768
769 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
770 value = value + 13;
771 /* Convert the value from ascii to integer */
772 ret = kstrtou8(value, 10, &roamRssiDiff);
773 if (ret < 0)
774 {
775 /* If the input value is greater than max value of datatype, then also
776 kstrtou8 fails */
777 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
778 "%s: kstrtou8 failed range [%d - %d]", __func__,
779 CFG_ROAM_RSSI_DIFF_MIN,
780 CFG_ROAM_RSSI_DIFF_MAX);
781 ret = -EINVAL;
782 goto exit;
783 }
784
785 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
786 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
787 {
788 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
789 "Roam rssi diff value %d is out of range"
790 " (Min: %d Max: %d)", roamRssiDiff,
791 CFG_ROAM_RSSI_DIFF_MIN,
792 CFG_ROAM_RSSI_DIFF_MAX);
793 ret = -EINVAL;
794 goto exit;
795 }
796
797 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
798 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
799
800 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
801 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
802 }
803 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
804 {
805 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
806 char extra[32];
807 tANI_U8 len = 0;
808
809 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
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#endif
819#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
820 else if (strncmp(command, "GETBAND", 7) == 0)
821 {
822 int band = -1;
823 char extra[32];
824 tANI_U8 len = 0;
825 hdd_getBand_helper(pHddCtx, &band);
826
827 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
828 if (copy_to_user(priv_data.buf, &extra, len + 1))
829 {
830 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
831 "%s: failed to copy data to user buffer", __func__);
832 ret = -EFAULT;
833 goto exit;
834 }
835 }
836 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
837 {
838 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
839 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
840 tANI_U8 revision = 0;
841 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
842 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
843 char extra[32] = {0};
844 tANI_U8 len = 0;
845
846 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
847 {
848 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
849 "%s: failed to get country code", __func__);
850 ret = -EFAULT;
851 goto exit;
852 }
853 pBuf[uBufLen] = '\0';
854 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
855
856 if (0 == strncmp(pBuf, "KR", 2))
857 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
858 else
859 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
860
861 if (copy_to_user(priv_data.buf, &extra, len + 1))
862 {
863 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
864 "%s: failed to copy data to user buffer", __func__);
865 ret = -EFAULT;
866 goto exit;
867 }
868 }
869 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
870 {
871 tANI_U8 *value = command;
872 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
873 tANI_U8 numChannels = 0;
874 eHalStatus status = eHAL_STATUS_SUCCESS;
875
876 status = hdd_parse_channellist(value, ChannelList, &numChannels);
877 if (eHAL_STATUS_SUCCESS != status)
878 {
879 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
880 "%s: Failed to parse channel list information", __func__);
881 ret = -EINVAL;
882 goto exit;
883 }
884
885 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
886 {
887 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
888 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
889 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
890 ret = -EINVAL;
891 goto exit;
892 }
893 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
894 numChannels);
895 if (eHAL_STATUS_SUCCESS != status)
896 {
897 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
898 "%s: Failed to update channel list information", __func__);
899 ret = -EINVAL;
900 goto exit;
901 }
902 }
903 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
904 {
905 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
906 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -0700907 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800908 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -0700909 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800910
911 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
912 ChannelList, &numChannels ))
913 {
914 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
915 "%s: failed to get roam scan channel list", __func__);
916 ret = -EFAULT;
917 goto exit;
918 }
919 /* output channel list is of the format
920 [Number of roam scan channels][Channel1][Channel2]... */
921 /* copy the number of channels in the 0th index */
922 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
923 for (j = 0; (j < numChannels); j++)
924 {
925 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
926 }
927
928 if (copy_to_user(priv_data.buf, &extra, len + 1))
929 {
930 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
931 "%s: failed to copy data to user buffer", __func__);
932 ret = -EFAULT;
933 goto exit;
934 }
935 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700936 else if (strncmp(command, "GETCCXMODE", 10) == 0)
937 {
938 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
939 char extra[32];
940 tANI_U8 len = 0;
941
942 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
943 if (copy_to_user(priv_data.buf, &extra, len + 1))
944 {
945 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
946 "%s: failed to copy data to user buffer", __func__);
947 ret = -EFAULT;
948 goto exit;
949 }
950 }
951 else if (strncmp(command, "GETOKCMODE", 10) == 0)
952 {
953 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
954 char extra[32];
955 tANI_U8 len = 0;
956
957 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
958 if (copy_to_user(priv_data.buf, &extra, len + 1))
959 {
960 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
961 "%s: failed to copy data to user buffer", __func__);
962 ret = -EFAULT;
963 goto exit;
964 }
965 }
966 else if (strncmp(command, "GETFASTROAM", 10) == 0)
967 {
968 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
969 char extra[32];
970 tANI_U8 len = 0;
971
972 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
973 if (copy_to_user(priv_data.buf, &extra, len + 1))
974 {
975 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
976 "%s: failed to copy data to user buffer", __func__);
977 ret = -EFAULT;
978 goto exit;
979 }
980 }
981 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
982 {
983 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
984 char extra[32];
985 tANI_U8 len = 0;
986
987 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
988 if (copy_to_user(priv_data.buf, &extra, len + 1))
989 {
990 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
991 "%s: failed to copy data to user buffer", __func__);
992 ret = -EFAULT;
993 goto exit;
994 }
995 }
996 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
997 {
998 tANI_U8 *value = command;
999 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1000
1001 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1002 value = value + 26;
1003 /* Convert the value from ascii to integer */
1004 ret = kstrtou8(value, 10, &minTime);
1005 if (ret < 0)
1006 {
1007 /* If the input value is greater than max value of datatype, then also
1008 kstrtou8 fails */
1009 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1010 "%s: kstrtou8 failed range [%d - %d]", __func__,
1011 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1012 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1013 ret = -EINVAL;
1014 goto exit;
1015 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001016 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1017 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1018 {
1019 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1020 "scan min channel time value %d is out of range"
1021 " (Min: %d Max: %d)", minTime,
1022 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1023 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1024 ret = -EINVAL;
1025 goto exit;
1026 }
1027
1028 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1029 "%s: Received Command to change channel min time = %d", __func__, minTime);
1030
1031 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1032 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1033 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001034 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1035 {
1036 tANI_U8 *value = command;
1037 tANI_U8 channel = 0;
1038 tANI_U8 dwellTime = 0;
1039 tANI_U8 bufLen = 0;
1040 tANI_U8 *buf = NULL;
1041 tSirMacAddr targetApBssid;
1042 eHalStatus status = eHAL_STATUS_SUCCESS;
1043 struct ieee80211_channel chan;
1044 tANI_U8 finalLen = 0;
1045 tANI_U8 *finalBuf = NULL;
1046 tANI_U8 temp = 0;
1047 u64 cookie;
1048 hdd_station_ctx_t *pHddStaCtx = NULL;
1049 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1050
1051 /* if not associated, no need to send action frame */
1052 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1053 {
1054 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1055 ret = -EINVAL;
1056 goto exit;
1057 }
1058
1059 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1060 &dwellTime, &buf, &bufLen);
1061 if (eHAL_STATUS_SUCCESS != status)
1062 {
1063 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1064 "%s: Failed to parse send action frame data", __func__);
1065 ret = -EINVAL;
1066 goto exit;
1067 }
1068
1069 /* if the target bssid is different from currently associated AP,
1070 then no need to send action frame */
1071 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1072 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1073 {
1074 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1075 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001076 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001077 goto exit;
1078 }
1079
1080 /* if the channel number is different from operating channel then
1081 no need to send action frame */
1082 if (channel != pHddStaCtx->conn_info.operationChannel)
1083 {
1084 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1085 "%s: channel(%d) is different from operating channel(%d)",
1086 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1087 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001088 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001089 goto exit;
1090 }
1091 chan.center_freq = sme_ChnToFreq(channel);
1092
1093 finalLen = bufLen + 24;
1094 finalBuf = vos_mem_malloc(finalLen);
1095 if (NULL == finalBuf)
1096 {
1097 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1098 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001099 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001100 goto exit;
1101 }
1102 vos_mem_zero(finalBuf, finalLen);
1103
1104 /* Fill subtype */
1105 temp = SIR_MAC_MGMT_ACTION << 4;
1106 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1107
1108 /* Fill type */
1109 temp = SIR_MAC_MGMT_FRAME;
1110 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1111
1112 /* Fill destination address (bssid of the AP) */
1113 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1114
1115 /* Fill BSSID (STA mac address) */
1116 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1117
1118 /* Fill source address (STA mac address) */
1119 vos_mem_copy(finalBuf + 16, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1120
1121 /* Fill received buffer from 24th address */
1122 vos_mem_copy(finalBuf + 24, buf, bufLen);
1123
Jeff Johnson11c33152013-04-16 17:52:40 -07001124 /* done with the parsed buffer */
1125 vos_mem_free(buf);
1126
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001127 wlan_hdd_action( NULL, dev, &chan, 0, NL80211_CHAN_HT20,
1128 1, dwellTime, finalBuf, finalLen, 1,
1129 1, &cookie );
1130 vos_mem_free(finalBuf);
1131 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001132 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1133 {
1134 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1135 char extra[32];
1136 tANI_U8 len = 0;
1137
1138 /* value is interms of msec */
1139 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1140 if (copy_to_user(priv_data.buf, &extra, len + 1))
1141 {
1142 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1143 "%s: failed to copy data to user buffer", __func__);
1144 ret = -EFAULT;
1145 goto exit;
1146 }
1147 }
1148 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1149 {
1150 tANI_U8 *value = command;
1151 tANI_U8 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
1152
1153 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1154 value = value + 19;
1155 /* Convert the value from ascii to integer */
1156 ret = kstrtou8(value, 10, &maxTime);
1157 if (ret < 0)
1158 {
1159 /* If the input value is greater than max value of datatype, then also
1160 kstrtou8 fails */
1161 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1162 "%s: kstrtou8 failed range [%d - %d]", __func__,
1163 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1164 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1165 ret = -EINVAL;
1166 goto exit;
1167 }
1168
1169 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1170 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1171 {
1172 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1173 "lfr mode value %d is out of range"
1174 " (Min: %d Max: %d)", maxTime,
1175 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1176 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1177 ret = -EINVAL;
1178 goto exit;
1179 }
1180
1181 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1182 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1183
1184 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
1185 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1186 }
1187 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1188 {
1189 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1190 char extra[32];
1191 tANI_U8 len = 0;
1192
1193 /* value is interms of msec */
1194 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1195 if (copy_to_user(priv_data.buf, &extra, len + 1))
1196 {
1197 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1198 "%s: failed to copy data to user buffer", __func__);
1199 ret = -EFAULT;
1200 goto exit;
1201 }
1202 }
1203 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1204 {
1205 tANI_U8 *value = command;
1206 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1207
1208 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1209 value = value + 16;
1210 /* Convert the value from ascii to integer */
1211 ret = kstrtou16(value, 10, &val);
1212 if (ret < 0)
1213 {
1214 /* If the input value is greater than max value of datatype, then also
1215 kstrtou16 fails */
1216 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1217 "%s: kstrtou16 failed range [%d - %d]", __func__,
1218 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1219 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1220 ret = -EINVAL;
1221 goto exit;
1222 }
1223
1224 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1225 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1226 {
1227 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1228 "scan home time value %d is out of range"
1229 " (Min: %d Max: %d)", val,
1230 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1231 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1232 ret = -EINVAL;
1233 goto exit;
1234 }
1235
1236 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1237 "%s: Received Command to change scan home time = %d", __func__, val);
1238
1239 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1240 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1241 }
1242 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1243 {
1244 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1245 char extra[32];
1246 tANI_U8 len = 0;
1247
1248 /* value is interms of msec */
1249 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1250 if (copy_to_user(priv_data.buf, &extra, len + 1))
1251 {
1252 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1253 "%s: failed to copy data to user buffer", __func__);
1254 ret = -EFAULT;
1255 goto exit;
1256 }
1257 }
1258 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1259 {
1260 tANI_U8 *value = command;
1261 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1262
1263 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1264 value = value + 17;
1265 /* Convert the value from ascii to integer */
1266 ret = kstrtou8(value, 10, &val);
1267 if (ret < 0)
1268 {
1269 /* If the input value is greater than max value of datatype, then also
1270 kstrtou8 fails */
1271 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1272 "%s: kstrtou8 failed range [%d - %d]", __func__,
1273 CFG_ROAM_INTRA_BAND_MIN,
1274 CFG_ROAM_INTRA_BAND_MAX);
1275 ret = -EINVAL;
1276 goto exit;
1277 }
1278
1279 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1280 (val > CFG_ROAM_INTRA_BAND_MAX))
1281 {
1282 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1283 "intra band mode value %d is out of range"
1284 " (Min: %d Max: %d)", val,
1285 CFG_ROAM_INTRA_BAND_MIN,
1286 CFG_ROAM_INTRA_BAND_MAX);
1287 ret = -EINVAL;
1288 goto exit;
1289 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001290 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1291 "%s: Received Command to change intra band = %d", __func__, val);
1292
1293 pHddCtx->cfg_ini->nRoamIntraBand = val;
1294 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1295 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001296 else if (strncmp(command, "SETWESMODE", 10) == 0)
1297 {
1298 tANI_U8 *value = command;
1299 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
1300
1301 /* Move pointer to ahead of SETWESMODE<delimiter> */
1302 value = value + 11;
1303 /* Convert the value from ascii to integer */
1304 ret = kstrtou8(value, 10, &wesMode);
1305 if (ret < 0)
1306 {
1307 /* If the input value is greater than max value of datatype, then also
1308 kstrtou8 fails */
1309 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1310 "%s: kstrtou8 failed range [%d - %d]", __func__,
1311 CFG_ENABLE_WES_MODE_NAME_MIN,
1312 CFG_ENABLE_WES_MODE_NAME_MAX);
1313 ret = -EINVAL;
1314 goto exit;
1315 }
1316
1317 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
1318 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
1319 {
1320 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1321 "WES Mode value %d is out of range"
1322 " (Min: %d Max: %d)", wesMode,
1323 CFG_ENABLE_WES_MODE_NAME_MIN,
1324 CFG_ENABLE_WES_MODE_NAME_MAX);
1325 ret = -EINVAL;
1326 goto exit;
1327 }
1328 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1329 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
1330
1331 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
1332 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
1333 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001334 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1335 {
1336 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1337 char extra[32];
1338 tANI_U8 len = 0;
1339
1340 /* value is interms of msec */
1341 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1342 if (copy_to_user(priv_data.buf, &extra, len + 1))
1343 {
1344 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1345 "%s: failed to copy data to user buffer", __func__);
1346 ret = -EFAULT;
1347 goto exit;
1348 }
1349 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001350 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
1351 {
1352 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
1353 char extra[32];
1354 tANI_U8 len = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001355
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001356 len = snprintf(extra, sizeof(extra), "%s %d", command, wesMode);
1357 if (copy_to_user(priv_data.buf, &extra, len + 1))
1358 {
1359 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1360 "%s: failed to copy data to user buffer", __func__);
1361 ret = -EFAULT;
1362 goto exit;
1363 }
1364 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001365#endif
1366#ifdef FEATURE_WLAN_LFR
1367 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1368 {
1369 tANI_U8 *value = command;
1370 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1371
1372 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1373 value = value + 12;
1374 /* Convert the value from ascii to integer */
1375 ret = kstrtou8(value, 10, &lfrMode);
1376 if (ret < 0)
1377 {
1378 /* If the input value is greater than max value of datatype, then also
1379 kstrtou8 fails */
1380 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1381 "%s: kstrtou8 failed range [%d - %d]", __func__,
1382 CFG_LFR_FEATURE_ENABLED_MIN,
1383 CFG_LFR_FEATURE_ENABLED_MAX);
1384 ret = -EINVAL;
1385 goto exit;
1386 }
1387
1388 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1389 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1390 {
1391 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1392 "lfr mode value %d is out of range"
1393 " (Min: %d Max: %d)", lfrMode,
1394 CFG_LFR_FEATURE_ENABLED_MIN,
1395 CFG_LFR_FEATURE_ENABLED_MAX);
1396 ret = -EINVAL;
1397 goto exit;
1398 }
1399
1400 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1401 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1402
1403 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1404 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1405 }
1406#endif
1407#ifdef WLAN_FEATURE_VOWIFI_11R
1408 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1409 {
1410 tANI_U8 *value = command;
1411 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1412
1413 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1414 value = value + 18;
1415 /* Convert the value from ascii to integer */
1416 ret = kstrtou8(value, 10, &ft);
1417 if (ret < 0)
1418 {
1419 /* If the input value is greater than max value of datatype, then also
1420 kstrtou8 fails */
1421 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1422 "%s: kstrtou8 failed range [%d - %d]", __func__,
1423 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1424 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1425 ret = -EINVAL;
1426 goto exit;
1427 }
1428
1429 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1430 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1431 {
1432 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1433 "ft mode value %d is out of range"
1434 " (Min: %d Max: %d)", ft,
1435 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1436 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1437 ret = -EINVAL;
1438 goto exit;
1439 }
1440
1441 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1442 "%s: Received Command to change ft mode = %d", __func__, ft);
1443
1444 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1445 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1446 }
1447#endif
1448#ifdef FEATURE_WLAN_CCX
1449 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1450 {
1451 tANI_U8 *value = command;
1452 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1453
1454 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1455 value = value + 11;
1456 /* Convert the value from ascii to integer */
1457 ret = kstrtou8(value, 10, &ccxMode);
1458 if (ret < 0)
1459 {
1460 /* If the input value is greater than max value of datatype, then also
1461 kstrtou8 fails */
1462 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1463 "%s: kstrtou8 failed range [%d - %d]", __func__,
1464 CFG_CCX_FEATURE_ENABLED_MIN,
1465 CFG_CCX_FEATURE_ENABLED_MAX);
1466 ret = -EINVAL;
1467 goto exit;
1468 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001469 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1470 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1471 {
1472 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1473 "Ccx mode value %d is out of range"
1474 " (Min: %d Max: %d)", ccxMode,
1475 CFG_CCX_FEATURE_ENABLED_MIN,
1476 CFG_CCX_FEATURE_ENABLED_MAX);
1477 ret = -EINVAL;
1478 goto exit;
1479 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001480 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1481 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1482
1483 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1484 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1485 }
1486#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001487 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1488 {
1489 tANI_U8 *value = command;
1490 tANI_BOOLEAN roamScanControl = 0;
1491
1492 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1493 value = value + 19;
1494 /* Convert the value from ascii to integer */
1495 ret = kstrtou8(value, 10, &roamScanControl);
1496 if (ret < 0)
1497 {
1498 /* If the input value is greater than max value of datatype, then also
1499 kstrtou8 fails */
1500 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1501 "%s: kstrtou8 failed ", __func__);
1502 ret = -EINVAL;
1503 goto exit;
1504 }
1505
1506 if (0 != roamScanControl)
1507 {
1508 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1509 "roam scan control invalid value = %d",
1510 roamScanControl);
1511 ret = -EINVAL;
1512 goto exit;
1513 }
1514 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1515 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1516
1517 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1518 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001519#ifdef FEATURE_WLAN_OKC
1520 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1521 {
1522 tANI_U8 *value = command;
1523 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1524
1525 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1526 value = value + 11;
1527 /* Convert the value from ascii to integer */
1528 ret = kstrtou8(value, 10, &okcMode);
1529 if (ret < 0)
1530 {
1531 /* If the input value is greater than max value of datatype, then also
1532 kstrtou8 fails */
1533 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1534 "%s: kstrtou8 failed range [%d - %d]", __func__,
1535 CFG_OKC_FEATURE_ENABLED_MIN,
1536 CFG_OKC_FEATURE_ENABLED_MAX);
1537 ret = -EINVAL;
1538 goto exit;
1539 }
1540
1541 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1542 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1543 {
1544 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1545 "Okc mode value %d is out of range"
1546 " (Min: %d Max: %d)", okcMode,
1547 CFG_OKC_FEATURE_ENABLED_MIN,
1548 CFG_OKC_FEATURE_ENABLED_MAX);
1549 ret = -EINVAL;
1550 goto exit;
1551 }
1552
1553 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1554 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1555
1556 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1557 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001558 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1559 {
1560 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1561 char extra[32];
1562 tANI_U8 len = 0;
1563
1564 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1565 if (copy_to_user(priv_data.buf, &extra, len + 1))
1566 {
1567 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1568 "%s: failed to copy data to user buffer", __func__);
1569 ret = -EFAULT;
1570 goto exit;
1571 }
1572 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001573#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001574 else {
1575 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
1576 __func__, command);
1577 }
1578
Jeff Johnson295189b2012-06-20 16:38:30 -07001579 }
1580exit:
1581 if (command)
1582 {
1583 kfree(command);
1584 }
1585 return ret;
1586}
1587
Srinivas Girigowdade697412013-02-14 16:31:48 -08001588#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1589void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
1590{
1591 eCsrBand band = -1;
1592 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
1593 switch (band)
1594 {
1595 case eCSR_BAND_ALL:
1596 *pBand = WLAN_HDD_UI_BAND_AUTO;
1597 break;
1598
1599 case eCSR_BAND_24:
1600 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
1601 break;
1602
1603 case eCSR_BAND_5G:
1604 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
1605 break;
1606
1607 default:
1608 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
1609 *pBand = -1;
1610 break;
1611 }
1612}
1613
1614/**---------------------------------------------------------------------------
1615
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001616 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
1617
1618 This function parses the send action frame data passed in the format
1619 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
1620
1621 \param - pValue Pointer to input country code revision
1622 \param - pTargetApBssid Pointer to target Ap bssid
1623 \param - pChannel Pointer to the Target AP channel
1624 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
1625 \param - pBuf Pointer to data
1626 \param - pBufLen Pointer to data length
1627
1628 \return - 0 for success non-zero for failure
1629
1630 --------------------------------------------------------------------------*/
1631VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
1632 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
1633{
1634 tANI_U8 *inPtr = pValue;
1635 tANI_U8 *dataEnd;
1636 int tempInt;
1637 int j = 0;
1638 int i = 0;
1639 int v = 0;
1640 tANI_U8 tempBuf[32];
1641 tANI_U8 tempByte = 0;
1642
1643 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1644 /*no argument after the command*/
1645 if (NULL == inPtr)
1646 {
1647 return -EINVAL;
1648 }
1649
1650 /*no space after the command*/
1651 else if (SPACE_ASCII_VALUE != *inPtr)
1652 {
1653 return -EINVAL;
1654 }
1655
1656 /*removing empty spaces*/
1657 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1658
1659 /*no argument followed by spaces*/
1660 if ('\0' == *inPtr)
1661 {
1662 return -EINVAL;
1663 }
1664
1665 /*getting the first argument ie the target AP bssid */
1666 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
1667 {
1668 return -EINVAL;
1669 }
1670 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
1671 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
1672 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
1673
1674 /* point to the next argument */
1675 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1676 /*no argument after the command*/
1677 if (NULL == inPtr) return -EINVAL;
1678
1679 /*removing empty spaces*/
1680 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1681
1682 /*no argument followed by spaces*/
1683 if ('\0' == *inPtr)
1684 {
1685 return -EINVAL;
1686 }
1687
1688 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07001689 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001690 v = kstrtos32(tempBuf, 10, &tempInt);
1691 if ( v < 0) return -EINVAL;
1692
1693 *pChannel = tempInt;
1694
1695 /* point to the next argument */
1696 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1697 /*no argument after the command*/
1698 if (NULL == inPtr) return -EINVAL;
1699 /*removing empty spaces*/
1700 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1701
1702 /*no argument followed by spaces*/
1703 if ('\0' == *inPtr)
1704 {
1705 return -EINVAL;
1706 }
1707
1708 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07001709 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001710 v = kstrtos32(tempBuf, 10, &tempInt);
1711 if ( v < 0) return -EINVAL;
1712
1713 *pDwellTime = tempInt;
1714
1715 /* point to the next argument */
1716 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1717 /*no argument after the command*/
1718 if (NULL == inPtr) return -EINVAL;
1719 /*removing empty spaces*/
1720 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1721
1722 /*no argument followed by spaces*/
1723 if ('\0' == *inPtr)
1724 {
1725 return -EINVAL;
1726 }
1727
1728 /* find the length of data */
1729 dataEnd = inPtr;
1730 while(('\0' != *dataEnd) )
1731 {
1732 dataEnd++;
1733 ++(*pBufLen);
1734 }
1735 if ( *pBufLen <= 0) return -EINVAL;
1736
1737 *pBuf = vos_mem_malloc(sizeof(*pBufLen));
1738 if (NULL == *pBuf)
1739 {
1740 hddLog(VOS_TRACE_LEVEL_FATAL,
1741 "%s: vos_mem_alloc failed ", __func__);
1742 return -EINVAL;
1743 }
1744
1745 /* the buffer received from the upper layer is character buffer,
1746 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
1747 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
1748 and f0 in 3rd location */
1749 for (i = 0, j = 0; j < *pBufLen; j += 2)
1750 {
1751 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
1752 (*pBuf)[i++] = tempByte;
1753 }
1754 *pBufLen = i;
1755 return VOS_STATUS_SUCCESS;
1756}
1757
1758#endif
1759/**---------------------------------------------------------------------------
1760
Srinivas Girigowdade697412013-02-14 16:31:48 -08001761 \brief hdd_parse_countryrev() - HDD Parse country code revision
1762
1763 This function parses the country code revision passed in the format
1764 SETCOUNTRYREV<space><Country code><space>revision
1765
1766 \param - pValue Pointer to input country code revision
1767 \param - pCountryCode Pointer to local output array to record country code
1768 \param - pRevision Pointer to store revision integer number
1769
1770 \return - 0 for success non-zero for failure
1771
1772 --------------------------------------------------------------------------*/
1773VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
1774{
1775 tANI_U8 *inPtr = pValue;
1776 int tempInt;
1777
1778 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1779 /*no argument after the command*/
1780 if (NULL == inPtr)
1781 {
1782 return -EINVAL;
1783 }
1784
1785 /*no space after the command*/
1786 else if (SPACE_ASCII_VALUE != *inPtr)
1787 {
1788 return -EINVAL;
1789 }
1790
1791 /*removing empty spaces*/
1792 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
1793
1794 /*no argument followed by spaces*/
1795 if ('\0' == *inPtr)
1796 {
1797 return -EINVAL;
1798 }
1799
1800 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07001801 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001802
1803 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1804 "Country code is : %s", pCountryCode);
1805
1806 /*inPtr pointing to the beginning of first space after country code */
1807 inPtr = strpbrk( inPtr, " " );
1808 /*no revision number after the country code argument */
1809 if (NULL == inPtr)
1810 {
1811 return -EINVAL;
1812 }
1813
1814 inPtr++;
1815
1816 /*removing empty space*/
1817 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1818
1819 /*no channel list after the number of channels argument and spaces*/
1820 if (0 == strncmp(pCountryCode, "KR", 2))
1821 {
1822 if ('\0' == *inPtr)
1823 {
1824 return -EINVAL;
1825 }
1826
1827 sscanf(inPtr, "%d", &tempInt);
1828 *pRevision = tempInt;
1829 }
1830 else
1831 {
1832 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1833 "Revision input is required only for Country KR");
1834 return -EINVAL;
1835 }
1836 return VOS_STATUS_SUCCESS;
1837}
1838
1839/**---------------------------------------------------------------------------
1840
1841 \brief hdd_parse_channellist() - HDD Parse channel list
1842
1843 This function parses the channel list passed in the format
1844 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001845 if the Number of channels (N) does not match with the actual number of channels passed
1846 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
1847 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
1848 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
1849 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08001850
1851 \param - pValue Pointer to input channel list
1852 \param - ChannelList Pointer to local output array to record channel list
1853 \param - pNumChannels Pointer to number of roam scan channels
1854
1855 \return - 0 for success non-zero for failure
1856
1857 --------------------------------------------------------------------------*/
1858VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
1859{
1860 tANI_U8 *inPtr = pValue;
1861 int tempInt;
1862 int j = 0;
1863 int v = 0;
1864 char buf[32];
1865
1866 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1867 /*no argument after the command*/
1868 if (NULL == inPtr)
1869 {
1870 return -EINVAL;
1871 }
1872
1873 /*no space after the command*/
1874 else if (SPACE_ASCII_VALUE != *inPtr)
1875 {
1876 return -EINVAL;
1877 }
1878
1879 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001880 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001881
1882 /*no argument followed by spaces*/
1883 if ('\0' == *inPtr)
1884 {
1885 return -EINVAL;
1886 }
1887
1888 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07001889 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001890 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001891 if ((v < 0) ||
1892 (tempInt <= 0) ||
1893 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
1894 {
1895 return -EINVAL;
1896 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001897
1898 *pNumChannels = tempInt;
1899
1900 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1901 "Number of channels are: %d", *pNumChannels);
1902
1903 for (j = 0; j < (*pNumChannels); j++)
1904 {
1905 /*inPtr pointing to the beginning of first space after number of channels*/
1906 inPtr = strpbrk( inPtr, " " );
1907 /*no channel list after the number of channels argument*/
1908 if (NULL == inPtr)
1909 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001910 if (0 != j)
1911 {
1912 *pNumChannels = j;
1913 return VOS_STATUS_SUCCESS;
1914 }
1915 else
1916 {
1917 return -EINVAL;
1918 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001919 }
1920
1921 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001922 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001923
1924 /*no channel list after the number of channels argument and spaces*/
1925 if ( '\0' == *inPtr )
1926 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001927 if (0 != j)
1928 {
1929 *pNumChannels = j;
1930 return VOS_STATUS_SUCCESS;
1931 }
1932 else
1933 {
1934 return -EINVAL;
1935 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001936 }
1937
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001938 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001939 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001940 if ((v < 0) ||
1941 (tempInt <= 0) ||
1942 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
1943 {
1944 return -EINVAL;
1945 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001946 pChannelList[j] = tempInt;
1947
1948 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1949 "Channel %d added to preferred channel list",
1950 pChannelList[j] );
1951 }
1952
Srinivas Girigowdade697412013-02-14 16:31:48 -08001953 return VOS_STATUS_SUCCESS;
1954}
1955
Jeff Johnson295189b2012-06-20 16:38:30 -07001956/**---------------------------------------------------------------------------
1957
1958 \brief hdd_open() - HDD Open function
1959
1960 This is called in response to ifconfig up
1961
1962 \param - dev Pointer to net_device structure
1963
1964 \return - 0 for success non-zero for failure
1965
1966 --------------------------------------------------------------------------*/
1967int hdd_open (struct net_device *dev)
1968{
1969 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1970 hdd_context_t *pHddCtx;
1971 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1972 VOS_STATUS status;
1973 v_BOOL_t in_standby = TRUE;
1974
1975 if (NULL == pAdapter)
1976 {
1977 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001978 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001979 return -ENODEV;
1980 }
1981
1982 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1983 if (NULL == pHddCtx)
1984 {
1985 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001986 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001987 return -ENODEV;
1988 }
1989
1990 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1991 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1992 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07001993 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
1994 {
1995 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
1996 __func__, pAdapter->device_mode);
1997 in_standby = FALSE;
1998 break;
1999 }
2000 else
2001 {
2002 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2003 pAdapterNode = pNext;
2004 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002005 }
2006
2007 if (TRUE == in_standby)
2008 {
2009 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2010 {
2011 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2012 "wlan out of power save", __func__);
2013 return -EINVAL;
2014 }
2015 }
2016
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002017 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002018 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2019 {
2020 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002021 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002022 /* Enable TX queues only when we are connected */
2023 netif_tx_start_all_queues(dev);
2024 }
2025
2026 return 0;
2027}
2028
2029int hdd_mon_open (struct net_device *dev)
2030{
2031 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2032
2033 if(pAdapter == NULL) {
2034 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002035 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002036 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002037 }
2038
2039 netif_start_queue(dev);
2040
2041 return 0;
2042}
2043/**---------------------------------------------------------------------------
2044
2045 \brief hdd_stop() - HDD stop function
2046
2047 This is called in response to ifconfig down
2048
2049 \param - dev Pointer to net_device structure
2050
2051 \return - 0 for success non-zero for failure
2052
2053 --------------------------------------------------------------------------*/
2054
2055int hdd_stop (struct net_device *dev)
2056{
2057 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2058 hdd_context_t *pHddCtx;
2059 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2060 VOS_STATUS status;
2061 v_BOOL_t enter_standby = TRUE;
2062
2063 ENTER();
2064
2065 if (NULL == pAdapter)
2066 {
2067 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002068 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002069 return -ENODEV;
2070 }
2071
2072 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2073 if (NULL == pHddCtx)
2074 {
2075 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002076 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002077 return -ENODEV;
2078 }
2079
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002080 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002081 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2082 netif_tx_disable(pAdapter->dev);
2083 netif_carrier_off(pAdapter->dev);
2084
2085
2086 /* SoftAP ifaces should never go in power save mode
2087 making sure same here. */
2088 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2089 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002090 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002091 )
2092 {
2093 /* SoftAP mode, so return from here */
2094 EXIT();
2095 return 0;
2096 }
2097
2098 /* Find if any iface is up then
2099 if any iface is up then can't put device to sleep/ power save mode. */
2100 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2101 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2102 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002103 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2104 {
2105 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
2106 "put device to sleep", __func__, pAdapter->device_mode);
2107 enter_standby = FALSE;
2108 break;
2109 }
2110 else
2111 {
2112 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2113 pAdapterNode = pNext;
2114 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002115 }
2116
2117 if (TRUE == enter_standby)
2118 {
2119 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2120 "entering standby", __func__);
2121 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2122 {
2123 /*log and return success*/
2124 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2125 "wlan in power save", __func__);
2126 }
2127 }
2128
2129 EXIT();
2130 return 0;
2131}
2132
2133/**---------------------------------------------------------------------------
2134
2135 \brief hdd_uninit() - HDD uninit function
2136
2137 This is called during the netdev unregister to uninitialize all data
2138associated with the device
2139
2140 \param - dev Pointer to net_device structure
2141
2142 \return - void
2143
2144 --------------------------------------------------------------------------*/
2145static void hdd_uninit (struct net_device *dev)
2146{
2147 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2148
2149 ENTER();
2150
2151 do
2152 {
2153 if (NULL == pAdapter)
2154 {
2155 hddLog(VOS_TRACE_LEVEL_FATAL,
2156 "%s: NULL pAdapter", __func__);
2157 break;
2158 }
2159
2160 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2161 {
2162 hddLog(VOS_TRACE_LEVEL_FATAL,
2163 "%s: Invalid magic", __func__);
2164 break;
2165 }
2166
2167 if (NULL == pAdapter->pHddCtx)
2168 {
2169 hddLog(VOS_TRACE_LEVEL_FATAL,
2170 "%s: NULL pHddCtx", __func__);
2171 break;
2172 }
2173
2174 if (dev != pAdapter->dev)
2175 {
2176 hddLog(VOS_TRACE_LEVEL_FATAL,
2177 "%s: Invalid device reference", __func__);
2178 /* we haven't validated all cases so let this go for now */
2179 }
2180
2181 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2182
2183 /* after uninit our adapter structure will no longer be valid */
2184 pAdapter->dev = NULL;
2185 pAdapter->magic = 0;
2186 } while (0);
2187
2188 EXIT();
2189}
2190
2191/**---------------------------------------------------------------------------
2192
2193 \brief hdd_release_firmware() -
2194
2195 This function calls the release firmware API to free the firmware buffer.
2196
2197 \param - pFileName Pointer to the File Name.
2198 pCtx - Pointer to the adapter .
2199
2200
2201 \return - 0 for success, non zero for failure
2202
2203 --------------------------------------------------------------------------*/
2204
2205VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2206{
2207 VOS_STATUS status = VOS_STATUS_SUCCESS;
2208 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2209 ENTER();
2210
2211
2212 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2213
2214 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2215
2216 if(pHddCtx->fw) {
2217 release_firmware(pHddCtx->fw);
2218 pHddCtx->fw = NULL;
2219 }
2220 else
2221 status = VOS_STATUS_E_FAILURE;
2222 }
2223 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2224 if(pHddCtx->nv) {
2225 release_firmware(pHddCtx->nv);
2226 pHddCtx->nv = NULL;
2227 }
2228 else
2229 status = VOS_STATUS_E_FAILURE;
2230
2231 }
2232
2233 EXIT();
2234 return status;
2235}
2236
2237/**---------------------------------------------------------------------------
2238
2239 \brief hdd_request_firmware() -
2240
2241 This function reads the firmware file using the request firmware
2242 API and returns the the firmware data and the firmware file size.
2243
2244 \param - pfileName - Pointer to the file name.
2245 - pCtx - Pointer to the adapter .
2246 - ppfw_data - Pointer to the pointer of the firmware data.
2247 - pSize - Pointer to the file size.
2248
2249 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2250
2251 --------------------------------------------------------------------------*/
2252
2253
2254VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2255{
2256 int status;
2257 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2258 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2259 ENTER();
2260
2261 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2262
2263 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2264
2265 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2266 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2267 __func__, pfileName);
2268 retval = VOS_STATUS_E_FAILURE;
2269 }
2270
2271 else {
2272 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2273 *pSize = pHddCtx->fw->size;
2274 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2275 __func__, *pSize);
2276 }
2277 }
2278 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2279
2280 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2281
2282 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2283 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2284 __func__, pfileName);
2285 retval = VOS_STATUS_E_FAILURE;
2286 }
2287
2288 else {
2289 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2290 *pSize = pHddCtx->nv->size;
2291 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2292 __func__, *pSize);
2293 }
2294 }
2295
2296 EXIT();
2297 return retval;
2298}
2299/**---------------------------------------------------------------------------
2300 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2301
2302 This is the function invoked by SME to inform the result of a full power
2303 request issued by HDD
2304
2305 \param - callbackcontext - Pointer to cookie
2306 status - result of request
2307
2308 \return - None
2309
2310--------------------------------------------------------------------------*/
2311void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2312{
2313 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2314
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002315 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002316 if(&pHddCtx->full_pwr_comp_var)
2317 {
2318 complete(&pHddCtx->full_pwr_comp_var);
2319 }
2320}
2321
2322/**---------------------------------------------------------------------------
2323
2324 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2325
2326 This is the function invoked by SME to inform the result of BMPS
2327 request issued by HDD
2328
2329 \param - callbackcontext - Pointer to cookie
2330 status - result of request
2331
2332 \return - None
2333
2334--------------------------------------------------------------------------*/
2335void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2336{
2337
2338 struct completion *completion_var = (struct completion*) callbackContext;
2339
2340 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2341 if(completion_var != NULL)
2342 {
2343 complete(completion_var);
2344 }
2345}
2346
2347/**---------------------------------------------------------------------------
2348
2349 \brief hdd_get_cfg_file_size() -
2350
2351 This function reads the configuration file using the request firmware
2352 API and returns the configuration file size.
2353
2354 \param - pCtx - Pointer to the adapter .
2355 - pFileName - Pointer to the file name.
2356 - pBufSize - Pointer to the buffer size.
2357
2358 \return - 0 for success, non zero for failure
2359
2360 --------------------------------------------------------------------------*/
2361
2362VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2363{
2364 int status;
2365 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2366
2367 ENTER();
2368
2369 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2370
2371 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2372 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2373 status = VOS_STATUS_E_FAILURE;
2374 }
2375 else {
2376 *pBufSize = pHddCtx->fw->size;
2377 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2378 release_firmware(pHddCtx->fw);
2379 pHddCtx->fw = NULL;
2380 }
2381
2382 EXIT();
2383 return VOS_STATUS_SUCCESS;
2384}
2385
2386/**---------------------------------------------------------------------------
2387
2388 \brief hdd_read_cfg_file() -
2389
2390 This function reads the configuration file using the request firmware
2391 API and returns the cfg data and the buffer size of the configuration file.
2392
2393 \param - pCtx - Pointer to the adapter .
2394 - pFileName - Pointer to the file name.
2395 - pBuffer - Pointer to the data buffer.
2396 - pBufSize - Pointer to the buffer size.
2397
2398 \return - 0 for success, non zero for failure
2399
2400 --------------------------------------------------------------------------*/
2401
2402VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2403 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2404{
2405 int status;
2406 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2407
2408 ENTER();
2409
2410 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2411
2412 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2413 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2414 return VOS_STATUS_E_FAILURE;
2415 }
2416 else {
2417 if(*pBufSize != pHddCtx->fw->size) {
2418 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2419 "file size", __func__);
2420 release_firmware(pHddCtx->fw);
2421 pHddCtx->fw = NULL;
2422 return VOS_STATUS_E_FAILURE;
2423 }
2424 else {
2425 if(pBuffer) {
2426 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2427 }
2428 release_firmware(pHddCtx->fw);
2429 pHddCtx->fw = NULL;
2430 }
2431 }
2432
2433 EXIT();
2434
2435 return VOS_STATUS_SUCCESS;
2436}
2437
2438/**---------------------------------------------------------------------------
2439
Jeff Johnson295189b2012-06-20 16:38:30 -07002440 \brief hdd_set_mac_address() -
2441
2442 This function sets the user specified mac address using
2443 the command ifconfig wlanX hw ether <mac adress>.
2444
2445 \param - dev - Pointer to the net device.
2446 - addr - Pointer to the sockaddr.
2447 \return - 0 for success, non zero for failure
2448
2449 --------------------------------------------------------------------------*/
2450
2451static int hdd_set_mac_address(struct net_device *dev, void *addr)
2452{
2453 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2454 struct sockaddr *psta_mac_addr = addr;
2455 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2456
2457 ENTER();
2458
2459 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2460
2461#ifdef HDD_SESSIONIZE
2462 // set the MAC address though the STA ID CFG.
2463 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2464 (v_U8_t *)&pAdapter->macAddressCurrent,
2465 sizeof( pAdapter->macAddressCurrent ),
2466 hdd_set_mac_addr_cb, VOS_FALSE );
2467#endif
2468
2469 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2470
2471 EXIT();
2472 return halStatus;
2473}
2474
2475tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2476{
2477 int i;
2478 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2479 {
2480 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2481 break;
2482 }
2483
2484 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2485 return NULL;
2486
2487 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2488 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2489}
2490
2491void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
2492{
2493 int i;
2494 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2495 {
2496 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
2497 {
2498 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
2499 break;
2500 }
2501 }
2502 return;
2503}
2504
2505#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2506 static struct net_device_ops wlan_drv_ops = {
2507 .ndo_open = hdd_open,
2508 .ndo_stop = hdd_stop,
2509 .ndo_uninit = hdd_uninit,
2510 .ndo_start_xmit = hdd_hard_start_xmit,
2511 .ndo_tx_timeout = hdd_tx_timeout,
2512 .ndo_get_stats = hdd_stats,
2513 .ndo_do_ioctl = hdd_ioctl,
2514 .ndo_set_mac_address = hdd_set_mac_address,
2515 .ndo_select_queue = hdd_select_queue,
2516#ifdef WLAN_FEATURE_PACKET_FILTERING
2517#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
2518 .ndo_set_rx_mode = hdd_set_multicast_list,
2519#else
2520 .ndo_set_multicast_list = hdd_set_multicast_list,
2521#endif //LINUX_VERSION_CODE
2522#endif
2523 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002524 static struct net_device_ops wlan_mon_drv_ops = {
2525 .ndo_open = hdd_mon_open,
2526 .ndo_stop = hdd_stop,
2527 .ndo_uninit = hdd_uninit,
2528 .ndo_start_xmit = hdd_mon_hard_start_xmit,
2529 .ndo_tx_timeout = hdd_tx_timeout,
2530 .ndo_get_stats = hdd_stats,
2531 .ndo_do_ioctl = hdd_ioctl,
2532 .ndo_set_mac_address = hdd_set_mac_address,
2533 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002534
2535#endif
2536
2537void hdd_set_station_ops( struct net_device *pWlanDev )
2538{
2539#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2540 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
2541 pWlanDev->netdev_ops = &wlan_drv_ops;
2542#else
2543 pWlanDev->open = hdd_open;
2544 pWlanDev->stop = hdd_stop;
2545 pWlanDev->uninit = hdd_uninit;
2546 pWlanDev->hard_start_xmit = NULL;
2547 pWlanDev->tx_timeout = hdd_tx_timeout;
2548 pWlanDev->get_stats = hdd_stats;
2549 pWlanDev->do_ioctl = hdd_ioctl;
2550 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
2551 pWlanDev->set_mac_address = hdd_set_mac_address;
2552#endif
2553}
2554
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002555static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07002556{
2557 struct net_device *pWlanDev = NULL;
2558 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002559 /*
2560 * cfg80211 initialization and registration....
2561 */
2562 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
2563
Jeff Johnson295189b2012-06-20 16:38:30 -07002564 if(pWlanDev != NULL)
2565 {
2566
2567 //Save the pointer to the net_device in the HDD adapter
2568 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
2569
Jeff Johnson295189b2012-06-20 16:38:30 -07002570 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
2571
2572 pAdapter->dev = pWlanDev;
2573 pAdapter->pHddCtx = pHddCtx;
2574 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
2575
2576 init_completion(&pAdapter->session_open_comp_var);
2577 init_completion(&pAdapter->session_close_comp_var);
2578 init_completion(&pAdapter->disconnect_comp_var);
2579 init_completion(&pAdapter->linkup_event_var);
2580 init_completion(&pAdapter->cancel_rem_on_chan_var);
2581 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07002582#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2583 init_completion(&pAdapter->offchannel_tx_event);
2584#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002585 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002586#ifdef FEATURE_WLAN_TDLS
2587 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002588 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002589 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002590#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002591 init_completion(&pHddCtx->mc_sus_event_var);
2592 init_completion(&pHddCtx->tx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07002593 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07002594
Jeff Johnson295189b2012-06-20 16:38:30 -07002595 pAdapter->isLinkUpSvcNeeded = FALSE;
2596 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
2597 //Init the net_device structure
2598 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2599
2600 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
2601 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
2602 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
2603 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
2604
2605 hdd_set_station_ops( pAdapter->dev );
2606
2607 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002608 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
2609 pAdapter->wdev.wiphy = pHddCtx->wiphy;
2610 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002611 /* set pWlanDev's parent to underlying device */
2612 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
2613 }
2614
2615 return pAdapter;
2616}
2617
2618VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
2619{
2620 struct net_device *pWlanDev = pAdapter->dev;
2621 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2622 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2623 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2624
2625 if( rtnl_lock_held )
2626 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08002627 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07002628 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
2629 {
2630 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
2631 return VOS_STATUS_E_FAILURE;
2632 }
2633 }
2634 if (register_netdevice(pWlanDev))
2635 {
2636 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
2637 return VOS_STATUS_E_FAILURE;
2638 }
2639 }
2640 else
2641 {
2642 if(register_netdev(pWlanDev))
2643 {
2644 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
2645 return VOS_STATUS_E_FAILURE;
2646 }
2647 }
2648 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
2649
2650 return VOS_STATUS_SUCCESS;
2651}
2652
2653eHalStatus hdd_smeCloseSessionCallback(void *pContext)
2654{
2655 if(pContext != NULL)
2656 {
2657 clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags);
2658
2659 /* need to make sure all of our scheduled work has completed.
2660 * This callback is called from MC thread context, so it is safe to
2661 * to call below flush workqueue API from here.
2662 */
2663 flush_scheduled_work();
2664 complete(&((hdd_adapter_t*)pContext)->session_close_comp_var);
2665 }
2666 return eHAL_STATUS_SUCCESS;
2667}
2668
2669VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
2670{
2671 struct net_device *pWlanDev = pAdapter->dev;
2672 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2673 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2674 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2675 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2676 int rc = 0;
2677
2678 INIT_COMPLETION(pAdapter->session_open_comp_var);
2679 //Open a SME session for future operation
2680 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
2681 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
2682 if ( !HAL_STATUS_SUCCESS( halStatus ) )
2683 {
2684 hddLog(VOS_TRACE_LEVEL_FATAL,
2685 "sme_OpenSession() failed with status code %08d [x%08lx]",
2686 halStatus, halStatus );
2687 status = VOS_STATUS_E_FAILURE;
2688 goto error_sme_open;
2689 }
2690
2691 //Block on a completion variable. Can't wait forever though.
2692 rc = wait_for_completion_interruptible_timeout(
2693 &pAdapter->session_open_comp_var,
2694 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2695 if (!rc)
2696 {
2697 hddLog(VOS_TRACE_LEVEL_FATAL,
2698 "Session is not opened within timeout period code %08d", rc );
2699 status = VOS_STATUS_E_FAILURE;
2700 goto error_sme_open;
2701 }
2702
2703 // Register wireless extensions
2704 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
2705 {
2706 hddLog(VOS_TRACE_LEVEL_FATAL,
2707 "hdd_register_wext() failed with status code %08d [x%08lx]",
2708 halStatus, halStatus );
2709 status = VOS_STATUS_E_FAILURE;
2710 goto error_register_wext;
2711 }
2712 //Safe to register the hard_start_xmit function again
2713#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2714 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
2715#else
2716 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
2717#endif
2718
2719 //Set the Connection State to Not Connected
2720 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2721
2722 //Set the default operation channel
2723 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
2724
2725 /* Make the default Auth Type as OPEN*/
2726 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2727
2728 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
2729 {
2730 hddLog(VOS_TRACE_LEVEL_FATAL,
2731 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
2732 status, status );
2733 goto error_init_txrx;
2734 }
2735
2736 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2737
2738 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
2739 {
2740 hddLog(VOS_TRACE_LEVEL_FATAL,
2741 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
2742 status, status );
2743 goto error_wmm_init;
2744 }
2745
2746 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2747
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002748#ifdef FEATURE_WLAN_TDLS
2749 if(0 != wlan_hdd_tdls_init(pAdapter))
2750 {
2751 status = VOS_STATUS_E_FAILURE;
2752 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
2753 goto error_tdls_init;
2754 }
2755 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2756#endif
2757
Jeff Johnson295189b2012-06-20 16:38:30 -07002758 return VOS_STATUS_SUCCESS;
2759
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002760#ifdef FEATURE_WLAN_TDLS
2761error_tdls_init:
2762 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2763 hdd_wmm_adapter_close(pAdapter);
2764#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002765error_wmm_init:
2766 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2767 hdd_deinit_tx_rx(pAdapter);
2768error_init_txrx:
2769 hdd_UnregisterWext(pWlanDev);
2770error_register_wext:
2771 if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
2772 {
2773 INIT_COMPLETION(pAdapter->session_close_comp_var);
2774 if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
2775 pAdapter->sessionId,
2776 hdd_smeCloseSessionCallback, pAdapter ) )
2777 {
2778 //Block on a completion variable. Can't wait forever though.
2779 wait_for_completion_interruptible_timeout(
2780 &pAdapter->session_close_comp_var,
2781 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2782 }
2783}
2784error_sme_open:
2785 return status;
2786}
2787
Jeff Johnson295189b2012-06-20 16:38:30 -07002788void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2789{
2790 hdd_cfg80211_state_t *cfgState;
2791
2792 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
2793
2794 if( NULL != cfgState->buf )
2795 {
2796 int rc;
2797 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
2798 rc = wait_for_completion_interruptible_timeout(
2799 &pAdapter->tx_action_cnf_event,
2800 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2801 if(!rc)
2802 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08002803 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07002804 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
2805 }
2806 }
2807 return;
2808}
Jeff Johnson295189b2012-06-20 16:38:30 -07002809
2810void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2811{
2812 ENTER();
2813 switch ( pAdapter->device_mode )
2814 {
2815 case WLAN_HDD_INFRA_STATION:
2816 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002817 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002818 {
2819 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2820 {
2821 hdd_deinit_tx_rx( pAdapter );
2822 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2823 }
2824
2825 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
2826 {
2827 hdd_wmm_adapter_close( pAdapter );
2828 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2829 }
2830
Jeff Johnson295189b2012-06-20 16:38:30 -07002831 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002832#ifdef FEATURE_WLAN_TDLS
2833 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
2834 {
2835 wlan_hdd_tdls_exit(pAdapter);
2836 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2837 }
2838#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002839
2840 break;
2841 }
2842
2843 case WLAN_HDD_SOFTAP:
2844 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002845 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002846 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002847
2848 hdd_unregister_hostapd(pAdapter);
2849 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07002850 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07002851 break;
2852 }
2853
2854 case WLAN_HDD_MONITOR:
2855 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002856 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07002857 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2858 {
2859 hdd_deinit_tx_rx( pAdapter );
2860 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2861 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002862 if(NULL != pAdapterforTx)
2863 {
2864 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
2865 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002866 break;
2867 }
2868
2869
2870 default:
2871 break;
2872 }
2873
2874 EXIT();
2875}
2876
2877void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
2878{
2879 struct net_device *pWlanDev = pAdapter->dev;
2880
2881 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
2882 if( rtnl_held )
2883 {
2884 unregister_netdevice(pWlanDev);
2885 }
2886 else
2887 {
2888 unregister_netdev(pWlanDev);
2889 }
2890 // note that the pAdapter is no longer valid at this point
2891 // since the memory has been reclaimed
2892 }
2893
2894}
2895
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08002896void hdd_set_pwrparams(hdd_context_t *pHddCtx)
2897{
2898 tSirSetPowerParamsReq powerRequest = { 0 };
2899
2900 powerRequest.uIgnoreDTIM = 1;
2901
2902 if (pHddCtx->cfg_ini->enableModulatedDTIM)
2903 {
2904 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
2905 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2906 }
2907 else
2908 {
2909 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
2910 }
2911
2912 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
2913 *specified during Enter/Exit BMPS when LCD off*/
2914 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2915 NULL, eANI_BOOLEAN_FALSE);
2916 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2917 NULL, eANI_BOOLEAN_FALSE);
2918
2919 /* switch to the DTIM specified in cfg.ini */
2920 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2921 "Switch to DTIM%d", powerRequest.uListenInterval);
2922 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2923
2924}
2925
2926void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
2927{
2928 /*Switch back to DTIM 1*/
2929 tSirSetPowerParamsReq powerRequest = { 0 };
2930
2931 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
2932 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2933
2934 /* Update ignoreDTIM and ListedInterval in CFG with default values */
2935 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2936 NULL, eANI_BOOLEAN_FALSE);
2937 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2938 NULL, eANI_BOOLEAN_FALSE);
2939
2940 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2941 "Switch to DTIM%d",powerRequest.uListenInterval);
2942 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2943
2944}
2945
Jeff Johnson295189b2012-06-20 16:38:30 -07002946VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
2947{
2948 VOS_STATUS status = VOS_STATUS_SUCCESS;
2949
2950 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2951 {
2952 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2953 }
2954
2955 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2956 {
2957 sme_StartAutoBmpsTimer(pHddCtx->hHal);
2958 }
2959
2960 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2961 {
2962 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2963 }
2964
2965 return status;
2966}
2967
2968VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
2969{
2970 hdd_adapter_t *pAdapter = NULL;
2971 eHalStatus halStatus;
2972 VOS_STATUS status = VOS_STATUS_E_INVAL;
2973 v_BOOL_t disableBmps = FALSE;
2974 v_BOOL_t disableImps = FALSE;
2975
2976 switch(session_type)
2977 {
2978 case WLAN_HDD_INFRA_STATION:
2979 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002980 case WLAN_HDD_P2P_CLIENT:
2981 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002982 //Exit BMPS -> Is Sta/P2P Client is already connected
2983 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
2984 if((NULL != pAdapter)&&
2985 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2986 {
2987 disableBmps = TRUE;
2988 }
2989
2990 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
2991 if((NULL != pAdapter)&&
2992 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2993 {
2994 disableBmps = TRUE;
2995 }
2996
2997 //Exit both Bmps and Imps incase of Go/SAP Mode
2998 if((WLAN_HDD_SOFTAP == session_type) ||
2999 (WLAN_HDD_P2P_GO == session_type))
3000 {
3001 disableBmps = TRUE;
3002 disableImps = TRUE;
3003 }
3004
3005 if(TRUE == disableImps)
3006 {
3007 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3008 {
3009 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3010 }
3011 }
3012
3013 if(TRUE == disableBmps)
3014 {
3015 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3016 {
3017 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3018
3019 if(eHAL_STATUS_SUCCESS != halStatus)
3020 {
3021 status = VOS_STATUS_E_FAILURE;
3022 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3023 VOS_ASSERT(0);
3024 return status;
3025 }
3026 }
3027
3028 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3029 {
3030 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3031
3032 if(eHAL_STATUS_SUCCESS != halStatus)
3033 {
3034 status = VOS_STATUS_E_FAILURE;
3035 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3036 VOS_ASSERT(0);
3037 return status;
3038 }
3039 }
3040 }
3041
3042 if((TRUE == disableBmps) ||
3043 (TRUE == disableImps))
3044 {
3045 /* Now, get the chip into Full Power now */
3046 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3047 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3048 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3049
3050 if(halStatus != eHAL_STATUS_SUCCESS)
3051 {
3052 if(halStatus == eHAL_STATUS_PMC_PENDING)
3053 {
3054 //Block on a completion variable. Can't wait forever though
3055 wait_for_completion_interruptible_timeout(
3056 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3057 }
3058 else
3059 {
3060 status = VOS_STATUS_E_FAILURE;
3061 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3062 VOS_ASSERT(0);
3063 return status;
3064 }
3065 }
3066
3067 status = VOS_STATUS_SUCCESS;
3068 }
3069
3070 break;
3071 }
3072 return status;
3073}
3074
3075hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003076 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003077 tANI_U8 rtnl_held )
3078{
3079 hdd_adapter_t *pAdapter = NULL;
3080 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3081 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3082 VOS_STATUS exitbmpsStatus;
3083
3084 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3085
3086 //Disable BMPS incase of Concurrency
3087 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3088
3089 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3090 {
3091 //Fail to Exit BMPS
3092 VOS_ASSERT(0);
3093 return NULL;
3094 }
3095
3096 switch(session_type)
3097 {
3098 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003099 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003100 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003101 {
3102 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3103
3104 if( NULL == pAdapter )
3105 return NULL;
3106
Jeff Johnsone7245742012-09-05 17:12:55 -07003107 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3108 NL80211_IFTYPE_P2P_CLIENT:
3109 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003110
Jeff Johnson295189b2012-06-20 16:38:30 -07003111 pAdapter->device_mode = session_type;
3112
3113 status = hdd_init_station_mode( pAdapter );
3114 if( VOS_STATUS_SUCCESS != status )
3115 goto err_free_netdev;
3116
3117 status = hdd_register_interface( pAdapter, rtnl_held );
3118 if( VOS_STATUS_SUCCESS != status )
3119 {
3120 hdd_deinit_adapter(pHddCtx, pAdapter);
3121 goto err_free_netdev;
3122 }
3123 //Stop the Interface TX queue.
3124 netif_tx_disable(pAdapter->dev);
3125 //netif_tx_disable(pWlanDev);
3126 netif_carrier_off(pAdapter->dev);
3127
3128 break;
3129 }
3130
Jeff Johnson295189b2012-06-20 16:38:30 -07003131 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003132 case WLAN_HDD_SOFTAP:
3133 {
3134 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3135 if( NULL == pAdapter )
3136 return NULL;
3137
Jeff Johnson295189b2012-06-20 16:38:30 -07003138 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3139 NL80211_IFTYPE_AP:
3140 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003141 pAdapter->device_mode = session_type;
3142
3143 status = hdd_init_ap_mode(pAdapter);
3144 if( VOS_STATUS_SUCCESS != status )
3145 goto err_free_netdev;
3146
3147 status = hdd_register_hostapd( pAdapter, rtnl_held );
3148 if( VOS_STATUS_SUCCESS != status )
3149 {
3150 hdd_deinit_adapter(pHddCtx, pAdapter);
3151 goto err_free_netdev;
3152 }
3153
3154 netif_tx_disable(pAdapter->dev);
3155 netif_carrier_off(pAdapter->dev);
3156
3157 hdd_set_conparam( 1 );
3158 break;
3159 }
3160 case WLAN_HDD_MONITOR:
3161 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003162 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3163 if( NULL == pAdapter )
3164 return NULL;
3165
3166 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3167 pAdapter->device_mode = session_type;
3168 status = hdd_register_interface( pAdapter, rtnl_held );
3169#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3170 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3171#else
3172 pAdapter->dev->open = hdd_mon_open;
3173 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3174#endif
3175 hdd_init_tx_rx( pAdapter );
3176 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3177 //Set adapter to be used for data tx. It will use either GO or softap.
3178 pAdapter->sessionCtx.monitor.pAdapterForTx =
3179 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003180 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3181 {
3182 pAdapter->sessionCtx.monitor.pAdapterForTx =
3183 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3184 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003185 /* This workqueue will be used to transmit management packet over
3186 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003187 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3188 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3189 return NULL;
3190 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003191
Jeff Johnson295189b2012-06-20 16:38:30 -07003192 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3193 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003194 }
3195 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003196 case WLAN_HDD_FTM:
3197 {
3198 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3199
3200 if( NULL == pAdapter )
3201 return NULL;
3202 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3203 * message while loading driver in FTM mode. */
3204 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3205 pAdapter->device_mode = session_type;
3206 status = hdd_register_interface( pAdapter, rtnl_held );
3207 }
3208 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003209 default:
3210 {
3211 VOS_ASSERT(0);
3212 return NULL;
3213 }
3214 }
3215
3216
3217 if( VOS_STATUS_SUCCESS == status )
3218 {
3219 //Add it to the hdd's session list.
3220 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3221 if( NULL == pHddAdapterNode )
3222 {
3223 status = VOS_STATUS_E_NOMEM;
3224 }
3225 else
3226 {
3227 pHddAdapterNode->pAdapter = pAdapter;
3228 status = hdd_add_adapter_back ( pHddCtx,
3229 pHddAdapterNode );
3230 }
3231 }
3232
3233 if( VOS_STATUS_SUCCESS != status )
3234 {
3235 if( NULL != pAdapter )
3236 {
3237 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3238 pAdapter = NULL;
3239 }
3240 if( NULL != pHddAdapterNode )
3241 {
3242 vos_mem_free( pHddAdapterNode );
3243 }
3244
3245 goto resume_bmps;
3246 }
3247
3248 if(VOS_STATUS_SUCCESS == status)
3249 {
3250 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3251
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003252 //Initialize the WoWL service
3253 if(!hdd_init_wowl(pAdapter))
3254 {
3255 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3256 goto err_free_netdev;
3257 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003258 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003259 return pAdapter;
3260
3261err_free_netdev:
3262 free_netdev(pAdapter->dev);
3263 wlan_hdd_release_intf_addr( pHddCtx,
3264 pAdapter->macAddressCurrent.bytes );
3265
3266resume_bmps:
3267 //If bmps disabled enable it
3268 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3269 {
3270 hdd_enable_bmps_imps(pHddCtx);
3271 }
3272 return NULL;
3273}
3274
3275VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3276 tANI_U8 rtnl_held )
3277{
3278 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3279 VOS_STATUS status;
3280
3281 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3282 if( VOS_STATUS_SUCCESS != status )
3283 return status;
3284
3285 while ( pCurrent->pAdapter != pAdapter )
3286 {
3287 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3288 if( VOS_STATUS_SUCCESS != status )
3289 break;
3290
3291 pCurrent = pNext;
3292 }
3293 pAdapterNode = pCurrent;
3294 if( VOS_STATUS_SUCCESS == status )
3295 {
3296 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3297 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3298 hdd_remove_adapter( pHddCtx, pAdapterNode );
3299 vos_mem_free( pAdapterNode );
3300
Jeff Johnson295189b2012-06-20 16:38:30 -07003301
3302 /* If there is a single session of STA/P2P client, re-enable BMPS */
3303 if ((!vos_concurrent_sessions_running()) &&
3304 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3305 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3306 {
3307 hdd_enable_bmps_imps(pHddCtx);
3308 }
3309
3310 return VOS_STATUS_SUCCESS;
3311 }
3312
3313 return VOS_STATUS_E_FAILURE;
3314}
3315
3316VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3317{
3318 hdd_adapter_list_node_t *pHddAdapterNode;
3319 VOS_STATUS status;
3320
3321 ENTER();
3322
3323 do
3324 {
3325 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3326 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3327 {
3328 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3329 vos_mem_free( pHddAdapterNode );
3330 }
3331 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3332
3333 EXIT();
3334
3335 return VOS_STATUS_SUCCESS;
3336}
3337
3338void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3339{
3340 v_U8_t addIE[1] = {0};
3341
3342 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3343 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3344 eANI_BOOLEAN_FALSE) )
3345 {
3346 hddLog(LOGE,
3347 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3348 }
3349
3350 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3351 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3352 eANI_BOOLEAN_FALSE) )
3353 {
3354 hddLog(LOGE,
3355 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3356 }
3357
3358 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3359 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3360 eANI_BOOLEAN_FALSE) )
3361 {
3362 hddLog(LOGE,
3363 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3364 }
3365}
3366
3367VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3368{
3369 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3370 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3371 union iwreq_data wrqu;
3372
3373 ENTER();
3374
3375 switch(pAdapter->device_mode)
3376 {
3377 case WLAN_HDD_INFRA_STATION:
3378 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003379 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003380 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3381 {
3382 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3383 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3384 pAdapter->sessionId,
3385 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3386 else
3387 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3388 pAdapter->sessionId,
3389 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3390 //success implies disconnect command got queued up successfully
3391 if(halStatus == eHAL_STATUS_SUCCESS)
3392 {
3393 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3394 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3395 }
3396 memset(&wrqu, '\0', sizeof(wrqu));
3397 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3398 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3399 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3400 }
3401 else
3402 {
3403 hdd_abort_mac_scan(pHddCtx);
3404 }
3405
3406 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3407 {
3408 INIT_COMPLETION(pAdapter->session_close_comp_var);
3409 if (eHAL_STATUS_SUCCESS ==
3410 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3411 hdd_smeCloseSessionCallback, pAdapter))
3412 {
3413 //Block on a completion variable. Can't wait forever though.
3414 wait_for_completion_interruptible_timeout(
3415 &pAdapter->session_close_comp_var,
3416 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3417 }
3418 }
3419
3420 break;
3421
3422 case WLAN_HDD_SOFTAP:
3423 case WLAN_HDD_P2P_GO:
3424 //Any softap specific cleanup here...
3425 mutex_lock(&pHddCtx->sap_lock);
3426 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3427 {
3428 VOS_STATUS status;
3429 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3430
3431 //Stop Bss.
3432 status = WLANSAP_StopBss(pHddCtx->pvosContext);
3433 if (VOS_IS_STATUS_SUCCESS(status))
3434 {
3435 hdd_hostapd_state_t *pHostapdState =
3436 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3437
3438 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
3439
3440 if (!VOS_IS_STATUS_SUCCESS(status))
3441 {
3442 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003443 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003444 }
3445 }
3446 else
3447 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003448 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003449 }
3450 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
3451
3452 if (eHAL_STATUS_FAILURE ==
3453 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
3454 0, NULL, eANI_BOOLEAN_FALSE))
3455 {
3456 hddLog(LOGE,
3457 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003458 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003459 }
3460
3461 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
3462 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
3463 eANI_BOOLEAN_FALSE) )
3464 {
3465 hddLog(LOGE,
3466 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
3467 }
3468
3469 // Reset WNI_CFG_PROBE_RSP Flags
3470 wlan_hdd_reset_prob_rspies(pAdapter);
3471 kfree(pAdapter->sessionCtx.ap.beacon);
3472 pAdapter->sessionCtx.ap.beacon = NULL;
3473 }
3474 mutex_unlock(&pHddCtx->sap_lock);
3475 break;
3476 case WLAN_HDD_MONITOR:
3477 break;
3478 default:
3479 break;
3480 }
3481
3482 EXIT();
3483 return VOS_STATUS_SUCCESS;
3484}
3485
3486VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
3487{
3488 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3489 VOS_STATUS status;
3490 hdd_adapter_t *pAdapter;
3491
3492 ENTER();
3493
3494 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3495
3496 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3497 {
3498 pAdapter = pAdapterNode->pAdapter;
3499 netif_tx_disable(pAdapter->dev);
3500 netif_carrier_off(pAdapter->dev);
3501
3502 hdd_stop_adapter( pHddCtx, pAdapter );
3503
3504 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3505 pAdapterNode = pNext;
3506 }
3507
3508 EXIT();
3509
3510 return VOS_STATUS_SUCCESS;
3511}
3512
3513VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
3514{
3515 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3516 VOS_STATUS status;
3517 hdd_adapter_t *pAdapter;
3518
3519 ENTER();
3520
3521 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3522
3523 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3524 {
3525 pAdapter = pAdapterNode->pAdapter;
3526 netif_tx_disable(pAdapter->dev);
3527 netif_carrier_off(pAdapter->dev);
3528
3529 //Record whether STA is associated
3530 pAdapter->sessionCtx.station.bSendDisconnect =
3531 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
3532 VOS_TRUE : VOS_FALSE;
3533
3534 hdd_deinit_tx_rx(pAdapter);
3535 hdd_wmm_adapter_close(pAdapter);
3536
3537 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3538 pAdapterNode = pNext;
3539 }
3540
3541 EXIT();
3542
3543 return VOS_STATUS_SUCCESS;
3544}
3545
3546VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
3547{
3548 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3549 VOS_STATUS status;
3550 hdd_adapter_t *pAdapter;
3551 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
3552
3553 ENTER();
3554
3555 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3556
3557 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3558 {
3559 pAdapter = pAdapterNode->pAdapter;
3560
3561 switch(pAdapter->device_mode)
3562 {
3563 case WLAN_HDD_INFRA_STATION:
3564 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003565 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003566 hdd_init_station_mode(pAdapter);
3567 /* Open the gates for HDD to receive Wext commands */
3568 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003569 pHddCtx->scan_info.mScanPending = FALSE;
3570 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003571
3572 //Trigger the initial scan
3573 hdd_wlan_initial_scan(pAdapter);
3574
3575 //Indicate disconnect event to supplicant if associated previously
3576 if(pAdapter->sessionCtx.station.bSendDisconnect)
3577 {
3578 union iwreq_data wrqu;
3579 memset(&wrqu, '\0', sizeof(wrqu));
3580 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3581 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3582 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3583 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
3584
Jeff Johnson295189b2012-06-20 16:38:30 -07003585 /* indicate disconnected event to nl80211 */
3586 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
3587 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003588 }
3589 break;
3590
3591 case WLAN_HDD_SOFTAP:
3592 /* softAP can handle SSR */
3593 break;
3594
3595 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003596 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
3597 __func__);
3598 /* event supplicant to restart */
3599 cfg80211_del_sta(pAdapter->dev,
3600 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003601 break;
3602
3603 case WLAN_HDD_MONITOR:
3604 /* monitor interface start */
3605 break;
3606 default:
3607 break;
3608 }
3609
3610 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3611 pAdapterNode = pNext;
3612 }
3613
3614 EXIT();
3615
3616 return VOS_STATUS_SUCCESS;
3617}
3618
3619VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
3620{
3621 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3622 hdd_adapter_t *pAdapter;
3623 VOS_STATUS status;
3624 v_U32_t roamId;
3625
3626 ENTER();
3627
3628 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3629
3630 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3631 {
3632 pAdapter = pAdapterNode->pAdapter;
3633
3634 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3635 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
3636 {
3637 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3638 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3639
3640 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3641 init_completion(&pAdapter->disconnect_comp_var);
3642 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
3643 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3644
3645 wait_for_completion_interruptible_timeout(
3646 &pAdapter->disconnect_comp_var,
3647 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3648
3649 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
3650 pHddCtx->isAmpAllowed = VOS_FALSE;
3651 sme_RoamConnect(pHddCtx->hHal,
3652 pAdapter->sessionId, &(pWextState->roamProfile),
3653 &roamId);
3654 }
3655
3656 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3657 pAdapterNode = pNext;
3658 }
3659
3660 EXIT();
3661
3662 return VOS_STATUS_SUCCESS;
3663}
3664
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07003665void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
3666{
3667 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3668 VOS_STATUS status;
3669 hdd_adapter_t *pAdapter;
3670 hdd_station_ctx_t *pHddStaCtx;
3671 hdd_ap_ctx_t *pHddApCtx;
3672 hdd_hostapd_state_t * pHostapdState;
3673 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
3674 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
3675 const char *p2pMode = "DEV";
3676 const char *ccMode = "Standalone";
3677 int n;
3678
3679 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3680 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3681 {
3682 pAdapter = pAdapterNode->pAdapter;
3683 switch (pAdapter->device_mode) {
3684 case WLAN_HDD_INFRA_STATION:
3685 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3686 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3687 staChannel = pHddStaCtx->conn_info.operationChannel;
3688 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
3689 }
3690 break;
3691 case WLAN_HDD_P2P_CLIENT:
3692 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3693 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3694 p2pChannel = pHddStaCtx->conn_info.operationChannel;
3695 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
3696 p2pMode = "CLI";
3697 }
3698 break;
3699 case WLAN_HDD_P2P_GO:
3700 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3701 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3702 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3703 p2pChannel = pHddApCtx->operatingChannel;
3704 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
3705 }
3706 p2pMode = "GO";
3707 break;
3708 case WLAN_HDD_SOFTAP:
3709 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3710 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3711 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3712 apChannel = pHddApCtx->operatingChannel;
3713 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
3714 }
3715 break;
3716 default:
3717 break;
3718 }
3719 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3720 pAdapterNode = pNext;
3721 }
3722 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
3723 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
3724 }
3725 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
3726 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
3727 if (p2pChannel > 0) {
3728 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
3729 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
3730 }
3731 if (apChannel > 0) {
3732 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
3733 apChannel, MAC_ADDR_ARRAY(apBssid));
3734 }
3735
3736 if (p2pChannel > 0 && apChannel > 0) {
3737 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
3738 }
3739}
3740
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003741bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07003742{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003743 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07003744}
3745
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003746/* Once SSR is disabled then it cannot be set. */
3747void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07003748{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003749 if (HDD_SSR_DISABLED == isSsrRequired)
3750 return;
3751
Jeff Johnson295189b2012-06-20 16:38:30 -07003752 isSsrRequired = value;
3753}
3754
3755VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
3756 hdd_adapter_list_node_t** ppAdapterNode)
3757{
3758 VOS_STATUS status;
3759 spin_lock(&pHddCtx->hddAdapters.lock);
3760 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
3761 (hdd_list_node_t**) ppAdapterNode );
3762 spin_unlock(&pHddCtx->hddAdapters.lock);
3763 return status;
3764}
3765
3766VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
3767 hdd_adapter_list_node_t* pAdapterNode,
3768 hdd_adapter_list_node_t** pNextAdapterNode)
3769{
3770 VOS_STATUS status;
3771 spin_lock(&pHddCtx->hddAdapters.lock);
3772 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
3773 (hdd_list_node_t*) pAdapterNode,
3774 (hdd_list_node_t**)pNextAdapterNode );
3775
3776 spin_unlock(&pHddCtx->hddAdapters.lock);
3777 return status;
3778}
3779
3780VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
3781 hdd_adapter_list_node_t* pAdapterNode)
3782{
3783 VOS_STATUS status;
3784 spin_lock(&pHddCtx->hddAdapters.lock);
3785 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
3786 &pAdapterNode->node );
3787 spin_unlock(&pHddCtx->hddAdapters.lock);
3788 return status;
3789}
3790
3791VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
3792 hdd_adapter_list_node_t** ppAdapterNode)
3793{
3794 VOS_STATUS status;
3795 spin_lock(&pHddCtx->hddAdapters.lock);
3796 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
3797 (hdd_list_node_t**) ppAdapterNode );
3798 spin_unlock(&pHddCtx->hddAdapters.lock);
3799 return status;
3800}
3801
3802VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
3803 hdd_adapter_list_node_t* pAdapterNode)
3804{
3805 VOS_STATUS status;
3806 spin_lock(&pHddCtx->hddAdapters.lock);
3807 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
3808 (hdd_list_node_t*) pAdapterNode );
3809 spin_unlock(&pHddCtx->hddAdapters.lock);
3810 return status;
3811}
3812
3813VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
3814 hdd_adapter_list_node_t* pAdapterNode)
3815{
3816 VOS_STATUS status;
3817 spin_lock(&pHddCtx->hddAdapters.lock);
3818 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
3819 (hdd_list_node_t*) pAdapterNode );
3820 spin_unlock(&pHddCtx->hddAdapters.lock);
3821 return status;
3822}
3823
3824hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
3825 tSirMacAddr macAddr )
3826{
3827 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3828 hdd_adapter_t *pAdapter;
3829 VOS_STATUS status;
3830
3831 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3832
3833 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3834 {
3835 pAdapter = pAdapterNode->pAdapter;
3836
3837 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
3838 macAddr, sizeof(tSirMacAddr) ) )
3839 {
3840 return pAdapter;
3841 }
3842 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3843 pAdapterNode = pNext;
3844 }
3845
3846 return NULL;
3847
3848}
3849
3850hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
3851{
3852 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3853 hdd_adapter_t *pAdapter;
3854 VOS_STATUS status;
3855
3856 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3857
3858 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3859 {
3860 pAdapter = pAdapterNode->pAdapter;
3861
3862 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
3863 IFNAMSIZ ) )
3864 {
3865 return pAdapter;
3866 }
3867 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3868 pAdapterNode = pNext;
3869 }
3870
3871 return NULL;
3872
3873}
3874
3875hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
3876{
3877 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3878 hdd_adapter_t *pAdapter;
3879 VOS_STATUS status;
3880
3881 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3882
3883 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3884 {
3885 pAdapter = pAdapterNode->pAdapter;
3886
3887 if( pAdapter && (mode == pAdapter->device_mode) )
3888 {
3889 return pAdapter;
3890 }
3891 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3892 pAdapterNode = pNext;
3893 }
3894
3895 return NULL;
3896
3897}
3898
3899//Remove this function later
3900hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
3901{
3902 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3903 hdd_adapter_t *pAdapter;
3904 VOS_STATUS status;
3905
3906 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3907
3908 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3909 {
3910 pAdapter = pAdapterNode->pAdapter;
3911
3912 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
3913 {
3914 return pAdapter;
3915 }
3916
3917 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3918 pAdapterNode = pNext;
3919 }
3920
3921 return NULL;
3922
3923}
3924
Jeff Johnson295189b2012-06-20 16:38:30 -07003925/**---------------------------------------------------------------------------
3926
3927 \brief hdd_set_monitor_tx_adapter() -
3928
3929 This API initializes the adapter to be used while transmitting on monitor
3930 adapter.
3931
3932 \param - pHddCtx - Pointer to the HDD context.
3933 pAdapter - Adapter that will used for TX. This can be NULL.
3934 \return - None.
3935 --------------------------------------------------------------------------*/
3936void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3937{
3938 hdd_adapter_t *pMonAdapter;
3939
3940 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
3941
3942 if( NULL != pMonAdapter )
3943 {
3944 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
3945 }
3946}
Jeff Johnson295189b2012-06-20 16:38:30 -07003947/**---------------------------------------------------------------------------
3948
3949 \brief hdd_select_queue() -
3950
3951 This API returns the operating channel of the requested device mode
3952
3953 \param - pHddCtx - Pointer to the HDD context.
3954 - mode - Device mode for which operating channel is required
3955 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
3956 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
3957 \return - channel number. "0" id the requested device is not found OR it is not connected.
3958 --------------------------------------------------------------------------*/
3959v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
3960{
3961 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3962 VOS_STATUS status;
3963 hdd_adapter_t *pAdapter;
3964 v_U8_t operatingChannel = 0;
3965
3966 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3967
3968 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3969 {
3970 pAdapter = pAdapterNode->pAdapter;
3971
3972 if( mode == pAdapter->device_mode )
3973 {
3974 switch(pAdapter->device_mode)
3975 {
3976 case WLAN_HDD_INFRA_STATION:
3977 case WLAN_HDD_P2P_CLIENT:
3978 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3979 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
3980 break;
3981 case WLAN_HDD_SOFTAP:
3982 case WLAN_HDD_P2P_GO:
3983 /*softap connection info */
3984 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3985 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
3986 break;
3987 default:
3988 break;
3989 }
3990
3991 break; //Found the device of interest. break the loop
3992 }
3993
3994 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3995 pAdapterNode = pNext;
3996 }
3997 return operatingChannel;
3998}
3999
4000#ifdef WLAN_FEATURE_PACKET_FILTERING
4001/**---------------------------------------------------------------------------
4002
4003 \brief hdd_set_multicast_list() -
4004
4005 This used to set the multicast address list.
4006
4007 \param - dev - Pointer to the WLAN device.
4008 - skb - Pointer to OS packet (sk_buff).
4009 \return - success/fail
4010
4011 --------------------------------------------------------------------------*/
4012static void hdd_set_multicast_list(struct net_device *dev)
4013{
4014 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004015 int mc_count;
4016 int i = 0;
4017 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304018
4019 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004020 {
4021 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304022 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004023 return;
4024 }
4025
4026 if (dev->flags & IFF_ALLMULTI)
4027 {
4028 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004029 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304030 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004031 }
4032 else
4033 {
4034 mc_count = netdev_mc_count(dev);
4035 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004036 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004037 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4038 {
4039 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004040 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304041 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004042 return;
4043 }
4044
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304045 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004046
4047 netdev_for_each_mc_addr(ha, dev) {
4048 if (i == mc_count)
4049 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304050 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4051 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4052 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004053 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304054 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004055 i++;
4056 }
4057 }
4058 return;
4059}
4060#endif
4061
4062/**---------------------------------------------------------------------------
4063
4064 \brief hdd_select_queue() -
4065
4066 This function is registered with the Linux OS for network
4067 core to decide which queue to use first.
4068
4069 \param - dev - Pointer to the WLAN device.
4070 - skb - Pointer to OS packet (sk_buff).
4071 \return - ac, Queue Index/access category corresponding to UP in IP header
4072
4073 --------------------------------------------------------------------------*/
4074v_U16_t hdd_select_queue(struct net_device *dev,
4075 struct sk_buff *skb)
4076{
4077 return hdd_wmm_select_queue(dev, skb);
4078}
4079
4080
4081/**---------------------------------------------------------------------------
4082
4083 \brief hdd_wlan_initial_scan() -
4084
4085 This function triggers the initial scan
4086
4087 \param - pAdapter - Pointer to the HDD adapter.
4088
4089 --------------------------------------------------------------------------*/
4090void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4091{
4092 tCsrScanRequest scanReq;
4093 tCsrChannelInfo channelInfo;
4094 eHalStatus halStatus;
4095 unsigned long scanId;
4096 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4097
4098 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4099 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4100 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4101
4102 if(sme_Is11dSupported(pHddCtx->hHal))
4103 {
4104 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4105 if ( HAL_STATUS_SUCCESS( halStatus ) )
4106 {
4107 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4108 if( !scanReq.ChannelInfo.ChannelList )
4109 {
4110 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4111 vos_mem_free(channelInfo.ChannelList);
4112 return;
4113 }
4114 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4115 channelInfo.numOfChannels);
4116 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4117 vos_mem_free(channelInfo.ChannelList);
4118 }
4119
4120 scanReq.scanType = eSIR_PASSIVE_SCAN;
4121 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4122 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4123 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4124 }
4125 else
4126 {
4127 scanReq.scanType = eSIR_ACTIVE_SCAN;
4128 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4129 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4130 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4131 }
4132
4133 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4134 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4135 {
4136 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4137 __func__, halStatus );
4138 }
4139
4140 if(sme_Is11dSupported(pHddCtx->hHal))
4141 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4142}
4143
4144struct fullPowerContext
4145{
4146 struct completion completion;
4147 unsigned int magic;
4148};
4149#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4150
4151/**---------------------------------------------------------------------------
4152
4153 \brief hdd_full_power_callback() - HDD full power callback function
4154
4155 This is the function invoked by SME to inform the result of a full power
4156 request issued by HDD
4157
4158 \param - callbackcontext - Pointer to cookie
4159 \param - status - result of request
4160
4161 \return - None
4162
4163 --------------------------------------------------------------------------*/
4164static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4165{
4166 struct fullPowerContext *pContext = callbackContext;
4167
4168 hddLog(VOS_TRACE_LEVEL_INFO,
4169 "%s: context = %p, status = %d", pContext, status);
4170
4171 if (NULL == callbackContext)
4172 {
4173 hddLog(VOS_TRACE_LEVEL_ERROR,
4174 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004175 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004176 return;
4177 }
4178
4179 /* there is a race condition that exists between this callback function
4180 and the caller since the caller could time out either before or
4181 while this code is executing. we'll assume the timeout hasn't
4182 occurred, but we'll verify that right before we save our work */
4183
4184 if (POWER_CONTEXT_MAGIC != pContext->magic)
4185 {
4186 /* the caller presumably timed out so there is nothing we can do */
4187 hddLog(VOS_TRACE_LEVEL_WARN,
4188 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004189 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004190 return;
4191 }
4192
4193 /* the race is on. caller could have timed out immediately after
4194 we verified the magic, but if so, caller will wait a short time
4195 for us to notify the caller, so the context will stay valid */
4196 complete(&pContext->completion);
4197}
4198
4199/**---------------------------------------------------------------------------
4200
4201 \brief hdd_wlan_exit() - HDD WLAN exit function
4202
4203 This is the driver exit point (invoked during rmmod)
4204
4205 \param - pHddCtx - Pointer to the HDD Context
4206
4207 \return - None
4208
4209 --------------------------------------------------------------------------*/
4210void hdd_wlan_exit(hdd_context_t *pHddCtx)
4211{
4212 eHalStatus halStatus;
4213 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4214 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304215 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004216 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004217 struct fullPowerContext powerContext;
4218 long lrc;
4219
4220 ENTER();
4221
Jeff Johnson88ba7742013-02-27 14:36:02 -08004222 if (VOS_FTM_MODE != hdd_get_conparam())
4223 {
4224 // Unloading, restart logic is no more required.
4225 wlan_hdd_restart_deinit(pHddCtx);
4226 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004227
Jeff Johnson295189b2012-06-20 16:38:30 -07004228 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004229 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004230 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004231 {
4232 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4233 WLAN_HDD_INFRA_STATION);
4234 if (pAdapter == NULL)
4235 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4236
4237 if (pAdapter != NULL)
4238 {
4239 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4240 hdd_UnregisterWext(pAdapter->dev);
4241 }
4242 }
4243 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004244
Jeff Johnson295189b2012-06-20 16:38:30 -07004245 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004246 {
4247 wlan_hdd_ftm_close(pHddCtx);
4248 goto free_hdd_ctx;
4249 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004250 //Stop the Interface TX queue.
4251 //netif_tx_disable(pWlanDev);
4252 //netif_carrier_off(pWlanDev);
4253
Jeff Johnson295189b2012-06-20 16:38:30 -07004254 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4255 {
4256 pAdapter = hdd_get_adapter(pHddCtx,
4257 WLAN_HDD_SOFTAP);
4258 }
4259 else
4260 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004261 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004262 {
4263 pAdapter = hdd_get_adapter(pHddCtx,
4264 WLAN_HDD_INFRA_STATION);
4265 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004266 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004267 /* DeRegister with platform driver as client for Suspend/Resume */
4268 vosStatus = hddDeregisterPmOps(pHddCtx);
4269 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4270 {
4271 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4272 VOS_ASSERT(0);
4273 }
4274
4275 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4276 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4277 {
4278 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4279 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004280
4281 // Cancel any outstanding scan requests. We are about to close all
4282 // of our adapters, but an adapter structure is what SME passes back
4283 // to our callback function. Hence if there are any outstanding scan
4284 // requests then there is a race condition between when the adapter
4285 // is closed and when the callback is invoked. We try to resolve that
4286 // race condition here by canceling any outstanding scans before we
4287 // close the adapters.
4288 // Note that the scans may be cancelled in an asynchronous manner, so
4289 // ideally there needs to be some kind of synchronization. Rather than
4290 // introduce a new synchronization here, we will utilize the fact that
4291 // we are about to Request Full Power, and since that is synchronized,
4292 // the expectation is that by the time Request Full Power has completed,
4293 // all scans will be cancelled.
4294 hdd_abort_mac_scan( pHddCtx );
4295
4296 //Disable IMPS/BMPS as we do not want the device to enter any power
4297 //save mode during shutdown
4298 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4299 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4300 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4301
4302 //Ensure that device is in full power as we will touch H/W during vos_Stop
4303 init_completion(&powerContext.completion);
4304 powerContext.magic = POWER_CONTEXT_MAGIC;
4305
4306 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4307 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4308
4309 if (eHAL_STATUS_SUCCESS != halStatus)
4310 {
4311 if (eHAL_STATUS_PMC_PENDING == halStatus)
4312 {
4313 /* request was sent -- wait for the response */
4314 lrc = wait_for_completion_interruptible_timeout(
4315 &powerContext.completion,
4316 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4317 /* either we have a response or we timed out
4318 either way, first invalidate our magic */
4319 powerContext.magic = 0;
4320 if (lrc <= 0)
4321 {
4322 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004323 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004324 /* there is a race condition such that the callback
4325 function could be executing at the same time we are. of
4326 primary concern is if the callback function had already
4327 verified the "magic" but hasn't yet set the completion
4328 variable. Since the completion variable is on our
4329 stack, we'll delay just a bit to make sure the data is
4330 still valid if that is the case */
4331 msleep(50);
4332 }
4333 }
4334 else
4335 {
4336 hddLog(VOS_TRACE_LEVEL_ERROR,
4337 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004338 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004339 VOS_ASSERT(0);
4340 /* continue -- need to clean up as much as possible */
4341 }
4342 }
4343
4344 // Unregister the Net Device Notifier
4345 unregister_netdevice_notifier(&hdd_netdev_notifier);
4346
Jeff Johnson295189b2012-06-20 16:38:30 -07004347 hdd_stop_all_adapters( pHddCtx );
4348
Jeff Johnson295189b2012-06-20 16:38:30 -07004349#ifdef WLAN_BTAMP_FEATURE
4350 vosStatus = WLANBAP_Stop(pVosContext);
4351 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4352 {
4353 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4354 "%s: Failed to stop BAP",__func__);
4355 }
4356#endif //WLAN_BTAMP_FEATURE
4357
4358 //Stop all the modules
4359 vosStatus = vos_stop( pVosContext );
4360 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4361 {
4362 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4363 "%s: Failed to stop VOSS",__func__);
4364 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4365 }
4366
Jeff Johnson295189b2012-06-20 16:38:30 -07004367 //Assert Deep sleep signal now to put Libra HW in lowest power state
4368 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4369 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4370
4371 //Vote off any PMIC voltage supplies
4372 vos_chipPowerDown(NULL, NULL, NULL);
4373
4374 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4375
4376 //Clean up HDD Nlink Service
4377 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
4378 nl_srv_exit();
4379
4380 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004381 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004382
4383 //Close the scheduler before calling vos_close to make sure no thread is
4384 // scheduled after the each module close is called i.e after all the data
4385 // structures are freed.
4386 vosStatus = vos_sched_close( pVosContext );
4387 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4388 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4389 "%s: Failed to close VOSS Scheduler",__func__);
4390 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4391 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004392#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004393#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4394 /* Destroy the wake lock */
4395 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4396#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004397 /* Destroy the wake lock */
4398 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004399#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004400
4401 //Close VOSS
4402 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4403 vos_close(pVosContext);
4404
Jeff Johnson295189b2012-06-20 16:38:30 -07004405 //Close Watchdog
4406 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4407 vos_watchdog_close(pVosContext);
4408
4409 /* Cancel the vote for XO Core ON.
4410 * This is done here to ensure there is no race condition since MC, TX and WD threads have
4411 * exited at this point
4412 */
4413 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
4414 " when WLAN is turned OFF\n");
4415 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4416 {
4417 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
4418 " Not returning failure."
4419 " Power consumed will be high\n");
4420 }
4421
4422 hdd_close_all_adapters( pHddCtx );
4423
4424
4425 //Free up dynamically allocated members inside HDD Adapter
4426 kfree(pHddCtx->cfg_ini);
4427 pHddCtx->cfg_ini= NULL;
4428
4429 /* free the power on lock from platform driver */
4430 if (free_riva_power_on_lock("wlan"))
4431 {
4432 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
4433 __func__);
4434 }
4435
Jeff Johnson88ba7742013-02-27 14:36:02 -08004436free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08004437 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004438 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004439 if (hdd_is_ssr_required())
4440 {
4441 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07004442 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07004443 msleep(5000);
4444 }
4445 hdd_set_ssr_required (VOS_FALSE);
4446}
4447
4448
4449/**---------------------------------------------------------------------------
4450
4451 \brief hdd_update_config_from_nv() - Function to update the contents of
4452 the running configuration with parameters taken from NV storage
4453
4454 \param - pHddCtx - Pointer to the HDD global context
4455
4456 \return - VOS_STATUS_SUCCESS if successful
4457
4458 --------------------------------------------------------------------------*/
4459static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
4460{
Jeff Johnson295189b2012-06-20 16:38:30 -07004461 v_BOOL_t itemIsValid = VOS_FALSE;
4462 VOS_STATUS status;
4463 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
4464 v_U8_t macLoop;
4465
4466 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
4467 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
4468 if(status != VOS_STATUS_SUCCESS)
4469 {
4470 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
4471 return VOS_STATUS_E_FAILURE;
4472 }
4473
4474 if (itemIsValid == VOS_TRUE)
4475 {
4476 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
4477 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
4478 VOS_MAX_CONCURRENCY_PERSONA);
4479 if(status != VOS_STATUS_SUCCESS)
4480 {
4481 /* Get MAC from NV fail, not update CFG info
4482 * INI MAC value will be used for MAC setting */
4483 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
4484 return VOS_STATUS_E_FAILURE;
4485 }
4486
4487 /* If first MAC is not valid, treat all others are not valid
4488 * Then all MACs will be got from ini file */
4489 if(vos_is_macaddr_zero(&macFromNV[0]))
4490 {
4491 /* MAC address in NV file is not configured yet */
4492 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
4493 return VOS_STATUS_E_INVAL;
4494 }
4495
4496 /* Get MAC address from NV, update CFG info */
4497 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
4498 {
4499 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
4500 {
4501 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
4502 /* This MAC is not valid, skip it
4503 * This MAC will be got from ini file */
4504 }
4505 else
4506 {
4507 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
4508 (v_U8_t *)&macFromNV[macLoop].bytes[0],
4509 VOS_MAC_ADDR_SIZE);
4510 }
4511 }
4512 }
4513 else
4514 {
4515 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
4516 return VOS_STATUS_E_FAILURE;
4517 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004518
Jeff Johnson295189b2012-06-20 16:38:30 -07004519
4520 return VOS_STATUS_SUCCESS;
4521}
4522
4523/**---------------------------------------------------------------------------
4524
4525 \brief hdd_post_voss_start_config() - HDD post voss start config helper
4526
4527 \param - pAdapter - Pointer to the HDD
4528
4529 \return - None
4530
4531 --------------------------------------------------------------------------*/
4532VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
4533{
4534 eHalStatus halStatus;
4535 v_U32_t listenInterval;
4536
Jeff Johnson295189b2012-06-20 16:38:30 -07004537
4538 // Send ready indication to the HDD. This will kick off the MAC
4539 // into a 'running' state and should kick off an initial scan.
4540 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
4541 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4542 {
4543 hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
4544 "code %08d [x%08x]",__func__, halStatus, halStatus );
4545 return VOS_STATUS_E_FAILURE;
4546 }
4547
4548 // Set default LI into HDD context,
4549 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
4550 // And RIVA will crash
4551 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
4552 pHddCtx->hdd_actual_LI_value = listenInterval;
4553
4554 return VOS_STATUS_SUCCESS;
4555}
4556
Jeff Johnson295189b2012-06-20 16:38:30 -07004557/* wake lock APIs for HDD */
4558void hdd_prevent_suspend(void)
4559{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004560#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004561 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004562#else
4563 wcnss_prevent_suspend();
4564#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004565}
4566
4567void hdd_allow_suspend(void)
4568{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004569#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004570 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004571#else
4572 wcnss_allow_suspend();
4573#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004574}
4575
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004576void hdd_allow_suspend_timeout(v_U32_t timeout)
4577{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004578#ifdef WLAN_OPEN_SOURCE
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004579 wake_lock_timeout(&wlan_wake_lock, timeout);
4580#else
4581 /* Do nothing as there is no API in wcnss for timeout*/
4582#endif
4583}
4584
Jeff Johnson295189b2012-06-20 16:38:30 -07004585/**---------------------------------------------------------------------------
4586
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004587 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
4588 information between Host and Riva
4589
4590 This function gets reported version of FW
4591 It also finds the version of Riva headers used to compile the host
4592 It compares the above two and prints a warning if they are different
4593 It gets the SW and HW version string
4594 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
4595 indicating the features they support through a bitmap
4596
4597 \param - pHddCtx - Pointer to HDD context
4598
4599 \return - void
4600
4601 --------------------------------------------------------------------------*/
4602
4603void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
4604{
4605
4606 tSirVersionType versionCompiled;
4607 tSirVersionType versionReported;
4608 tSirVersionString versionString;
4609 tANI_U8 fwFeatCapsMsgSupported = 0;
4610 VOS_STATUS vstatus;
4611
4612 /* retrieve and display WCNSS version information */
4613 do {
4614
4615 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
4616 &versionCompiled);
4617 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4618 {
4619 hddLog(VOS_TRACE_LEVEL_FATAL,
4620 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004621 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004622 break;
4623 }
4624
4625 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
4626 &versionReported);
4627 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4628 {
4629 hddLog(VOS_TRACE_LEVEL_FATAL,
4630 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004631 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004632 break;
4633 }
4634
4635 if ((versionCompiled.major != versionReported.major) ||
4636 (versionCompiled.minor != versionReported.minor) ||
4637 (versionCompiled.version != versionReported.version) ||
4638 (versionCompiled.revision != versionReported.revision))
4639 {
4640 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4641 "Host expected %u.%u.%u.%u\n",
4642 WLAN_MODULE_NAME,
4643 (int)versionReported.major,
4644 (int)versionReported.minor,
4645 (int)versionReported.version,
4646 (int)versionReported.revision,
4647 (int)versionCompiled.major,
4648 (int)versionCompiled.minor,
4649 (int)versionCompiled.version,
4650 (int)versionCompiled.revision);
4651 }
4652 else
4653 {
4654 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4655 WLAN_MODULE_NAME,
4656 (int)versionReported.major,
4657 (int)versionReported.minor,
4658 (int)versionReported.version,
4659 (int)versionReported.revision);
4660 }
4661
4662 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
4663 versionString,
4664 sizeof(versionString));
4665 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4666 {
4667 hddLog(VOS_TRACE_LEVEL_FATAL,
4668 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004669 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004670 break;
4671 }
4672
4673 pr_info("%s: WCNSS software version %s\n",
4674 WLAN_MODULE_NAME, versionString);
4675
4676 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
4677 versionString,
4678 sizeof(versionString));
4679 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4680 {
4681 hddLog(VOS_TRACE_LEVEL_FATAL,
4682 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004683 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004684 break;
4685 }
4686
4687 pr_info("%s: WCNSS hardware version %s\n",
4688 WLAN_MODULE_NAME, versionString);
4689
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004690 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
4691 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004692 send the message only if it the riva is 1.1
4693 minor numbers for different riva branches:
4694 0 -> (1.0)Mainline Build
4695 1 -> (1.1)Mainline Build
4696 2->(1.04) Stability Build
4697 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004698 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004699 ((versionReported.minor>=1) && (versionReported.version>=1)))
4700 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
4701 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004702
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004703 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08004704 {
4705#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4706 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
4707 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
4708#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004709 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08004710 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004711
4712 } while (0);
4713
4714}
4715
4716/**---------------------------------------------------------------------------
4717
Jeff Johnson295189b2012-06-20 16:38:30 -07004718 \brief hdd_wlan_startup() - HDD init function
4719
4720 This is the driver startup code executed once a WLAN device has been detected
4721
4722 \param - dev - Pointer to the underlying device
4723
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004724 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07004725
4726 --------------------------------------------------------------------------*/
4727
4728int hdd_wlan_startup(struct device *dev )
4729{
4730 VOS_STATUS status;
4731 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004732 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004733 hdd_context_t *pHddCtx = NULL;
4734 v_CONTEXT_t pVosContext= NULL;
4735#ifdef WLAN_BTAMP_FEATURE
4736 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
4737 WLANBAP_ConfigType btAmpConfig;
4738 hdd_config_t *pConfig;
4739#endif
4740 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07004741 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004742
4743 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07004744 /*
4745 * cfg80211: wiphy allocation
4746 */
4747 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
4748
4749 if(wiphy == NULL)
4750 {
4751 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004752 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004753 }
4754
4755 pHddCtx = wiphy_priv(wiphy);
4756
Jeff Johnson295189b2012-06-20 16:38:30 -07004757 //Initialize the adapter context to zeros.
4758 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
4759
Jeff Johnson295189b2012-06-20 16:38:30 -07004760 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004761 hdd_prevent_suspend();
4762 pHddCtx->isLoadUnloadInProgress = TRUE;
4763
4764 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4765
4766 /*Get vos context here bcoz vos_open requires it*/
4767 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4768
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08004769 if(pVosContext == NULL)
4770 {
4771 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
4772 goto err_free_hdd_context;
4773 }
4774
Jeff Johnson295189b2012-06-20 16:38:30 -07004775 //Save the Global VOSS context in adapter context for future.
4776 pHddCtx->pvosContext = pVosContext;
4777
4778 //Save the adapter context in global context for future.
4779 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
4780
Jeff Johnson295189b2012-06-20 16:38:30 -07004781 pHddCtx->parent_dev = dev;
4782
4783 init_completion(&pHddCtx->full_pwr_comp_var);
4784 init_completion(&pHddCtx->standby_comp_var);
4785 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004786 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004787 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004788
4789 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
4790
4791 // Load all config first as TL config is needed during vos_open
4792 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
4793 if(pHddCtx->cfg_ini == NULL)
4794 {
4795 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
4796 goto err_free_hdd_context;
4797 }
4798
4799 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
4800
4801 // Read and parse the qcom_cfg.ini file
4802 status = hdd_parse_config_ini( pHddCtx );
4803 if ( VOS_STATUS_SUCCESS != status )
4804 {
4805 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
4806 __func__, WLAN_INI_FILE);
4807 goto err_config;
4808 }
4809
Jeff Johnson295189b2012-06-20 16:38:30 -07004810 /*
4811 * cfg80211: Initialization and registration ...
4812 */
4813 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
4814 {
4815 hddLog(VOS_TRACE_LEVEL_FATAL,
4816 "%s: wlan_hdd_cfg80211_register return failure", __func__);
4817 goto err_wiphy_reg;
4818 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004819
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004820 // Update VOS trace levels based upon the cfg.ini
4821 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
4822 pHddCtx->cfg_ini->vosTraceEnableBAP);
4823 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
4824 pHddCtx->cfg_ini->vosTraceEnableTL);
4825 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
4826 pHddCtx->cfg_ini->vosTraceEnableWDI);
4827 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
4828 pHddCtx->cfg_ini->vosTraceEnableHDD);
4829 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
4830 pHddCtx->cfg_ini->vosTraceEnableSME);
4831 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
4832 pHddCtx->cfg_ini->vosTraceEnablePE);
4833 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
4834 pHddCtx->cfg_ini->vosTraceEnableWDA);
4835 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
4836 pHddCtx->cfg_ini->vosTraceEnableSYS);
4837 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
4838 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004839 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
4840 pHddCtx->cfg_ini->vosTraceEnableSAP);
4841 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
4842 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004843
Jeff Johnson295189b2012-06-20 16:38:30 -07004844 // Update WDI trace levels based upon the cfg.ini
4845 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
4846 pHddCtx->cfg_ini->wdiTraceEnableDAL);
4847 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
4848 pHddCtx->cfg_ini->wdiTraceEnableCTL);
4849 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
4850 pHddCtx->cfg_ini->wdiTraceEnableDAT);
4851 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
4852 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004853
Jeff Johnson88ba7742013-02-27 14:36:02 -08004854 if (VOS_FTM_MODE == hdd_get_conparam())
4855 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004856 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
4857 {
4858 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
4859 goto err_free_hdd_context;
4860 }
4861 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
4862 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08004863 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004864
Jeff Johnson88ba7742013-02-27 14:36:02 -08004865 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07004866 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4867 {
4868 status = vos_watchdog_open(pVosContext,
4869 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
4870
4871 if(!VOS_IS_STATUS_SUCCESS( status ))
4872 {
4873 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004874 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07004875 }
4876 }
4877
4878 pHddCtx->isLogpInProgress = FALSE;
4879 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4880
Jeff Johnson295189b2012-06-20 16:38:30 -07004881 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
4882 if(!VOS_IS_STATUS_SUCCESS(status))
4883 {
4884 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004885 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004886 }
4887
Jeff Johnson295189b2012-06-20 16:38:30 -07004888 status = vos_open( &pVosContext, 0);
4889 if ( !VOS_IS_STATUS_SUCCESS( status ))
4890 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004891 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
4892 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07004893 }
4894
Jeff Johnson295189b2012-06-20 16:38:30 -07004895 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
4896
4897 if ( NULL == pHddCtx->hHal )
4898 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004899 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004900 goto err_vosclose;
4901 }
4902
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004903 status = vos_preStart( pHddCtx->pvosContext );
4904 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4905 {
4906 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
4907 goto err_vosclose;
4908 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004909
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004910 /* Note that the vos_preStart() sequence triggers the cfg download.
4911 The cfg download must occur before we update the SME config
4912 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07004913 status = hdd_set_sme_config( pHddCtx );
4914
4915 if ( VOS_STATUS_SUCCESS != status )
4916 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004917 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
4918 goto err_vosclose;
4919 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004920
4921 //Initialize the WMM module
4922 status = hdd_wmm_init(pHddCtx);
4923 if (!VOS_IS_STATUS_SUCCESS(status))
4924 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004925 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004926 goto err_vosclose;
4927 }
4928
Jeff Johnson295189b2012-06-20 16:38:30 -07004929 /* In the integrated architecture we update the configuration from
4930 the INI file and from NV before vOSS has been started so that
4931 the final contents are available to send down to the cCPU */
4932
4933 // Apply the cfg.ini to cfg.dat
4934 if (FALSE == hdd_update_config_dat(pHddCtx))
4935 {
4936 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
4937 goto err_vosclose;
4938 }
4939
4940 // Apply the NV to cfg.dat
4941 /* Prima Update MAC address only at here */
4942 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
4943 {
4944#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
4945 /* There was not a valid set of MAC Addresses in NV. See if the
4946 default addresses were modified by the cfg.ini settings. If so,
4947 we'll use them, but if not, we'll autogenerate a set of MAC
4948 addresses based upon the device serial number */
4949
4950 static const v_MACADDR_t default_address =
4951 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
4952 unsigned int serialno;
4953 int i;
4954
4955 serialno = wcnss_get_serial_number();
4956 if ((0 != serialno) &&
4957 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
4958 sizeof(default_address))))
4959 {
4960 /* cfg.ini has the default address, invoke autogen logic */
4961
4962 /* MAC address has 3 bytes of OUI so we have a maximum of 3
4963 bytes of the serial number that can be used to generate
4964 the other 3 bytes of the MAC address. Mask off all but
4965 the lower 3 bytes (this will also make sure we don't
4966 overflow in the next step) */
4967 serialno &= 0x00FFFFFF;
4968
4969 /* we need a unique address for each session */
4970 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
4971
4972 /* autogen all addresses */
4973 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4974 {
4975 /* start with the entire default address */
4976 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
4977 /* then replace the lower 3 bytes */
4978 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
4979 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
4980 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
4981
4982 serialno++;
4983 }
4984
4985 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
4986 MAC_ADDRESS_STR,
4987 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4988 }
4989 else
4990#endif //WLAN_AUTOGEN_MACADDR_FEATURE
4991 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004992 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004993 "%s: Invalid MAC address in NV, using MAC from ini file "
4994 MAC_ADDRESS_STR, __func__,
4995 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4996 }
4997 }
4998 {
4999 eHalStatus halStatus;
5000 // Set the MAC Address
5001 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5002 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5003 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5004 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5005
5006 if (!HAL_STATUS_SUCCESS( halStatus ))
5007 {
5008 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5009 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005010 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005011 }
5012 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005013
5014 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5015 Note: Firmware image will be read and downloaded inside vos_start API */
5016 status = vos_start( pHddCtx->pvosContext );
5017 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5018 {
5019 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5020 goto err_vosclose;
5021 }
5022
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005023 /* Exchange capability info between Host and FW and also get versioning info from FW */
5024 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005025
5026 status = hdd_post_voss_start_config( pHddCtx );
5027 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5028 {
5029 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5030 __func__);
5031 goto err_vosstop;
5032 }
5033
Jeff Johnson295189b2012-06-20 16:38:30 -07005034 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5035 {
5036 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5037 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5038 }
5039 else
5040 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005041 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5042 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5043 if (pAdapter != NULL)
5044 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305045 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005046 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305047 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5048 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5049 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005050
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305051 /* Generate the P2P Device Address. This consists of the device's
5052 * primary MAC address with the locally administered bit set.
5053 */
5054 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005055 }
5056 else
5057 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305058 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5059 if (p2p_dev_addr != NULL)
5060 {
5061 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5062 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5063 }
5064 else
5065 {
5066 hddLog(VOS_TRACE_LEVEL_FATAL,
5067 "%s: Failed to allocate mac_address for p2p_device",
5068 __func__);
5069 goto err_close_adapter;
5070 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005071 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005072
5073 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5074 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5075 if ( NULL == pP2pAdapter )
5076 {
5077 hddLog(VOS_TRACE_LEVEL_FATAL,
5078 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005079 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005080 goto err_close_adapter;
5081 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005082 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005083 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005084
5085 if( pAdapter == NULL )
5086 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005087 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5088 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005089 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005090
Jeff Johnson295189b2012-06-20 16:38:30 -07005091#ifdef WLAN_BTAMP_FEATURE
5092 vStatus = WLANBAP_Open(pVosContext);
5093 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5094 {
5095 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5096 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005097 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005098 }
5099
5100 vStatus = BSL_Init(pVosContext);
5101 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5102 {
5103 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5104 "%s: Failed to Init BSL",__func__);
5105 goto err_bap_close;
5106 }
5107 vStatus = WLANBAP_Start(pVosContext);
5108 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5109 {
5110 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5111 "%s: Failed to start TL",__func__);
5112 goto err_bap_close;
5113 }
5114
5115 pConfig = pHddCtx->cfg_ini;
5116 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5117 status = WLANBAP_SetConfig(&btAmpConfig);
5118
5119#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005120
Jeff Johnson295189b2012-06-20 16:38:30 -07005121#ifdef FEATURE_WLAN_SCAN_PNO
5122 /*SME must send channel update configuration to RIVA*/
5123 sme_UpdateChannelConfig(pHddCtx->hHal);
5124#endif
5125
Jeff Johnson295189b2012-06-20 16:38:30 -07005126 /* Register with platform driver as client for Suspend/Resume */
5127 status = hddRegisterPmOps(pHddCtx);
5128 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5129 {
5130 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5131#ifdef WLAN_BTAMP_FEATURE
5132 goto err_bap_stop;
5133#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005134 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005135#endif //WLAN_BTAMP_FEATURE
5136 }
5137
5138 /* Register TM level change handler function to the platform */
5139 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5140 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5141 {
5142 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5143 goto err_unregister_pmops;
5144 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005145
5146 /* register for riva power on lock to platform driver */
5147 if (req_riva_power_on_lock("wlan"))
5148 {
5149 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5150 __func__);
5151 goto err_unregister_pmops;
5152 }
5153
Jeff Johnson295189b2012-06-20 16:38:30 -07005154 // register net device notifier for device change notification
5155 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5156
5157 if(ret < 0)
5158 {
5159 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5160 goto err_free_power_on_lock;
5161 }
5162
5163 //Initialize the nlink service
5164 if(nl_srv_init() != 0)
5165 {
5166 hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
5167 goto err_reg_netdev;
5168 }
5169
5170 //Initialize the BTC service
5171 if(btc_activate_service(pHddCtx) != 0)
5172 {
5173 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5174 goto err_nl_srv;
5175 }
5176
5177#ifdef PTT_SOCK_SVC_ENABLE
5178 //Initialize the PTT service
5179 if(ptt_sock_activate_svc(pHddCtx) != 0)
5180 {
5181 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5182 goto err_nl_srv;
5183 }
5184#endif
5185
Jeff Johnson295189b2012-06-20 16:38:30 -07005186 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005187 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005188 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005189 /* Action frame registered in one adapter which will
5190 * applicable to all interfaces
5191 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005192 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005193 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005194
5195 mutex_init(&pHddCtx->sap_lock);
5196
5197 pHddCtx->isLoadUnloadInProgress = FALSE;
5198
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005199#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005200#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5201 /* Initialize the wake lcok */
5202 wake_lock_init(&pHddCtx->rx_wake_lock,
5203 WAKE_LOCK_SUSPEND,
5204 "qcom_rx_wakelock");
5205#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005206 /* Initialize the wake lcok */
5207 wake_lock_init(&pHddCtx->sap_wake_lock,
5208 WAKE_LOCK_SUSPEND,
5209 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005210#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005211
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005212 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5213 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005214
5215 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5216 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005217
5218 // Initialize the restart logic
5219 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305220
Jeff Johnson295189b2012-06-20 16:38:30 -07005221 goto success;
5222
5223err_nl_srv:
5224 nl_srv_exit();
5225
5226err_reg_netdev:
5227 unregister_netdevice_notifier(&hdd_netdev_notifier);
5228
5229err_free_power_on_lock:
5230 free_riva_power_on_lock("wlan");
5231
5232err_unregister_pmops:
5233 hddDevTmUnregisterNotifyCallback(pHddCtx);
5234 hddDeregisterPmOps(pHddCtx);
5235
5236#ifdef WLAN_BTAMP_FEATURE
5237err_bap_stop:
5238 WLANBAP_Stop(pVosContext);
5239#endif
5240
5241#ifdef WLAN_BTAMP_FEATURE
5242err_bap_close:
5243 WLANBAP_Close(pVosContext);
5244#endif
5245
Jeff Johnson295189b2012-06-20 16:38:30 -07005246err_close_adapter:
5247 hdd_close_all_adapters( pHddCtx );
5248
5249err_vosstop:
5250 vos_stop(pVosContext);
5251
5252err_vosclose:
5253 status = vos_sched_close( pVosContext );
5254 if (!VOS_IS_STATUS_SUCCESS(status)) {
5255 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5256 "%s: Failed to close VOSS Scheduler", __func__);
5257 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5258 }
5259 vos_close(pVosContext );
5260
Jeff Johnson295189b2012-06-20 16:38:30 -07005261err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005262 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005263
5264err_wdclose:
5265 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5266 vos_watchdog_close(pVosContext);
5267
Jeff Johnson295189b2012-06-20 16:38:30 -07005268err_wiphy_reg:
5269 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005270
5271err_config:
5272 kfree(pHddCtx->cfg_ini);
5273 pHddCtx->cfg_ini= NULL;
5274
5275err_free_hdd_context:
5276 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005277 wiphy_free(wiphy) ;
5278 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005279 VOS_BUG(1);
5280
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005281 if (hdd_is_ssr_required())
5282 {
5283 /* WDI timeout had happened during load, so SSR is needed here */
5284 subsystem_restart("wcnss");
5285 msleep(5000);
5286 }
5287 hdd_set_ssr_required (VOS_FALSE);
5288
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005289 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005290
5291success:
5292 EXIT();
5293 return 0;
5294}
5295
5296/**---------------------------------------------------------------------------
5297
Jeff Johnson32d95a32012-09-10 13:15:23 -07005298 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07005299
Jeff Johnson32d95a32012-09-10 13:15:23 -07005300 This is the driver entry point - called in different timeline depending
5301 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07005302
5303 \param - None
5304
5305 \return - 0 for success, non zero for failure
5306
5307 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07005308static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005309{
5310 VOS_STATUS status;
5311 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005312 struct device *dev = NULL;
5313 int ret_status = 0;
5314
5315 ENTER();
5316
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005317#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005318 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07005319#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005320
5321 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
5322 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
5323
5324 //Power Up Libra WLAN card first if not already powered up
5325 status = vos_chipPowerUp(NULL,NULL,NULL);
5326 if (!VOS_IS_STATUS_SUCCESS(status))
5327 {
5328 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
5329 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005330 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005331 }
5332
Jeff Johnson295189b2012-06-20 16:38:30 -07005333#ifdef ANI_BUS_TYPE_PCI
5334
5335 dev = wcnss_wlan_get_device();
5336
5337#endif // ANI_BUS_TYPE_PCI
5338
5339#ifdef ANI_BUS_TYPE_PLATFORM
5340 dev = wcnss_wlan_get_device();
5341#endif // ANI_BUS_TYPE_PLATFORM
5342
5343
5344 do {
5345 if (NULL == dev) {
5346 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
5347 ret_status = -1;
5348 break;
5349 }
5350
5351#ifdef MEMORY_DEBUG
5352 vos_mem_init();
5353#endif
5354
5355#ifdef TIMER_MANAGER
5356 vos_timer_manager_init();
5357#endif
5358
5359 /* Preopen VOSS so that it is ready to start at least SAL */
5360 status = vos_preOpen(&pVosContext);
5361
5362 if (!VOS_IS_STATUS_SUCCESS(status))
5363 {
5364 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
5365 ret_status = -1;
5366 break;
5367 }
5368
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005369#ifndef MODULE
5370 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
5371 */
5372 hdd_set_conparam((v_UINT_t)con_mode);
5373#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005374
5375 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005376 if (hdd_wlan_startup(dev))
5377 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005378 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005379 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005380 vos_preClose( &pVosContext );
5381 ret_status = -1;
5382 break;
5383 }
5384
5385 /* Cancel the vote for XO Core ON
5386 * This is done here for safety purposes in case we re-initialize without turning
5387 * it OFF in any error scenario.
5388 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005389 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07005390 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005391 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07005392 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5393 {
5394 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
5395 " Power consumed will be high\n");
5396 }
5397 } while (0);
5398
5399 if (0 != ret_status)
5400 {
5401 //Assert Deep sleep signal now to put Libra HW in lowest power state
5402 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5403 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
5404
5405 //Vote off any PMIC voltage supplies
5406 vos_chipPowerDown(NULL, NULL, NULL);
5407#ifdef TIMER_MANAGER
5408 vos_timer_exit();
5409#endif
5410#ifdef MEMORY_DEBUG
5411 vos_mem_exit();
5412#endif
5413
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005414#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005415 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005416#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005417 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
5418 }
5419 else
5420 {
5421 //Send WLAN UP indication to Nlink Service
5422 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
5423
5424 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
5425
5426 }
5427
5428 EXIT();
5429
5430 return ret_status;
5431}
5432
Jeff Johnson32d95a32012-09-10 13:15:23 -07005433/**---------------------------------------------------------------------------
5434
5435 \brief hdd_module_init() - Init Function
5436
5437 This is the driver entry point (invoked when module is loaded using insmod)
5438
5439 \param - None
5440
5441 \return - 0 for success, non zero for failure
5442
5443 --------------------------------------------------------------------------*/
5444#ifdef MODULE
5445static int __init hdd_module_init ( void)
5446{
5447 return hdd_driver_init();
5448}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005449#else /* #ifdef MODULE */
5450static int __init hdd_module_init ( void)
5451{
5452 /* Driver initialization is delayed to fwpath_changed_handler */
5453 return 0;
5454}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005455#endif /* #ifdef MODULE */
5456
Jeff Johnson295189b2012-06-20 16:38:30 -07005457
5458/**---------------------------------------------------------------------------
5459
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005460 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005461
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005462 This is the driver exit point (invoked when module is unloaded using rmmod
5463 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07005464
5465 \param - None
5466
5467 \return - None
5468
5469 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005470static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005471{
5472 hdd_context_t *pHddCtx = NULL;
5473 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005474
5475 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
5476
5477 //Get the global vos context
5478 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5479
5480 if(!pVosContext)
5481 {
5482 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
5483 goto done;
5484 }
5485
5486 //Get the HDD context.
5487 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
5488
5489 if(!pHddCtx)
5490 {
5491 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
5492 }
5493 else
5494 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005495 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07005496 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07005497 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
5498 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07005499 }
5500
5501 pHddCtx->isLoadUnloadInProgress = TRUE;
5502 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5503
5504 //Do all the cleanup before deregistering the driver
5505 hdd_wlan_exit(pHddCtx);
5506 }
5507
Jeff Johnson295189b2012-06-20 16:38:30 -07005508 vos_preClose( &pVosContext );
5509
5510#ifdef TIMER_MANAGER
5511 vos_timer_exit();
5512#endif
5513#ifdef MEMORY_DEBUG
5514 vos_mem_exit();
5515#endif
5516
5517done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005518#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005519 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005520#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005521 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
5522}
5523
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005524/**---------------------------------------------------------------------------
5525
5526 \brief hdd_module_exit() - Exit function
5527
5528 This is the driver exit point (invoked when module is unloaded using rmmod)
5529
5530 \param - None
5531
5532 \return - None
5533
5534 --------------------------------------------------------------------------*/
5535static void __exit hdd_module_exit(void)
5536{
5537 hdd_driver_exit();
5538}
5539
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005540#ifdef MODULE
5541static int fwpath_changed_handler(const char *kmessage,
5542 struct kernel_param *kp)
5543{
Jeff Johnson76052702013-04-16 13:55:05 -07005544 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005545}
5546
5547static int con_mode_handler(const char *kmessage,
5548 struct kernel_param *kp)
5549{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07005550 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005551}
5552#else /* #ifdef MODULE */
5553/**---------------------------------------------------------------------------
5554
Jeff Johnson76052702013-04-16 13:55:05 -07005555 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005556
Jeff Johnson76052702013-04-16 13:55:05 -07005557 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005558 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07005559 - invoked when module parameter fwpath is modified from userspace to signal
5560 initializing the WLAN driver or when con_mode is modified from userspace
5561 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005562
5563 \return - 0 for success, non zero for failure
5564
5565 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07005566static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005567{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005568 int ret_status;
5569
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005570 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005571 ret_status = hdd_driver_init();
5572 wlan_hdd_inited = ret_status ? 0 : 1;
5573 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005574 }
5575
5576 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07005577
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005578 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07005579
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005580 ret_status = hdd_driver_init();
5581 wlan_hdd_inited = ret_status ? 0 : 1;
5582 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005583}
5584
Jeff Johnson295189b2012-06-20 16:38:30 -07005585/**---------------------------------------------------------------------------
5586
Jeff Johnson76052702013-04-16 13:55:05 -07005587 \brief fwpath_changed_handler() - Handler Function
5588
5589 Handle changes to the fwpath parameter
5590
5591 \return - 0 for success, non zero for failure
5592
5593 --------------------------------------------------------------------------*/
5594static int fwpath_changed_handler(const char *kmessage,
5595 struct kernel_param *kp)
5596{
5597 int ret;
5598
5599 ret = param_set_copystring(kmessage, kp);
5600 if (0 == ret)
5601 ret = kickstart_driver();
5602 return ret;
5603}
5604
5605/**---------------------------------------------------------------------------
5606
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005607 \brief con_mode_handler() -
5608
5609 Handler function for module param con_mode when it is changed by userspace
5610 Dynamically linked - do nothing
5611 Statically linked - exit and init driver, as in rmmod and insmod
5612
Jeff Johnson76052702013-04-16 13:55:05 -07005613 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005614
Jeff Johnson76052702013-04-16 13:55:05 -07005615 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005616
5617 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07005618static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005619{
Jeff Johnson76052702013-04-16 13:55:05 -07005620 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005621
Jeff Johnson76052702013-04-16 13:55:05 -07005622 ret = param_set_int(kmessage, kp);
5623 if (0 == ret)
5624 ret = kickstart_driver();
5625 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005626}
5627#endif /* #ifdef MODULE */
5628
5629/**---------------------------------------------------------------------------
5630
Jeff Johnson295189b2012-06-20 16:38:30 -07005631 \brief hdd_get_conparam() -
5632
5633 This is the driver exit point (invoked when module is unloaded using rmmod)
5634
5635 \param - None
5636
5637 \return - tVOS_CON_MODE
5638
5639 --------------------------------------------------------------------------*/
5640tVOS_CON_MODE hdd_get_conparam ( void )
5641{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005642#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07005643 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005644#else
5645 return (tVOS_CON_MODE)curr_con_mode;
5646#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005647}
5648void hdd_set_conparam ( v_UINT_t newParam )
5649{
5650 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005651#ifndef MODULE
5652 curr_con_mode = con_mode;
5653#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005654}
5655/**---------------------------------------------------------------------------
5656
5657 \brief hdd_softap_sta_deauth() - function
5658
5659 This to take counter measure to handle deauth req from HDD
5660
5661 \param - pAdapter - Pointer to the HDD
5662
5663 \param - enable - boolean value
5664
5665 \return - None
5666
5667 --------------------------------------------------------------------------*/
5668
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005669VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07005670{
Jeff Johnson295189b2012-06-20 16:38:30 -07005671 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005672 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07005673
5674 ENTER();
5675
5676 hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5677
5678 //Ignore request to deauth bcmc station
5679 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005680 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005681
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005682 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07005683
5684 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005685 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005686}
5687
5688/**---------------------------------------------------------------------------
5689
5690 \brief hdd_softap_sta_disassoc() - function
5691
5692 This to take counter measure to handle deauth req from HDD
5693
5694 \param - pAdapter - Pointer to the HDD
5695
5696 \param - enable - boolean value
5697
5698 \return - None
5699
5700 --------------------------------------------------------------------------*/
5701
5702void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
5703{
5704 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5705
5706 ENTER();
5707
5708 hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5709
5710 //Ignore request to disassoc bcmc station
5711 if( pDestMacAddress[0] & 0x1 )
5712 return;
5713
5714 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
5715}
5716
5717void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
5718{
5719 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5720
5721 ENTER();
5722
5723 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5724
5725 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
5726}
5727
Jeff Johnson295189b2012-06-20 16:38:30 -07005728/**---------------------------------------------------------------------------
5729 *
5730 * \brief hdd_get__concurrency_mode() -
5731 *
5732 *
5733 * \param - None
5734 *
5735 * \return - CONCURRENCY MODE
5736 *
5737 * --------------------------------------------------------------------------*/
5738tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
5739{
5740 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5741 hdd_context_t *pHddCtx;
5742
5743 if (NULL != pVosContext)
5744 {
5745 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5746 if (NULL != pHddCtx)
5747 {
5748 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
5749 }
5750 }
5751
5752 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005753 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005754 return VOS_STA;
5755}
5756
5757/* Decide whether to allow/not the apps power collapse.
5758 * Allow apps power collapse if we are in connected state.
5759 * if not, allow only if we are in IMPS */
5760v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
5761{
5762 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08005763 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005764 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07005765 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5766 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5767 hdd_adapter_t *pAdapter = NULL;
5768 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08005769 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005770
Jeff Johnson295189b2012-06-20 16:38:30 -07005771 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5772 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005773
Yathish9f22e662012-12-10 14:21:35 -08005774 concurrent_state = hdd_get_concurrency_mode();
5775
5776#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5777 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
5778 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
5779 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
5780 return TRUE;
5781#endif
5782
Jeff Johnson295189b2012-06-20 16:38:30 -07005783 /*loop through all adapters. TBD fix for Concurrency */
5784 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5785 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5786 {
5787 pAdapter = pAdapterNode->pAdapter;
5788 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
5789 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5790 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005791 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07005792 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08005793 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005794 (eANI_BOOLEAN_TRUE == scanRspPending) ||
5795 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07005796 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005797 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005798 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
5799 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07005800 return FALSE;
5801 }
5802 }
5803 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5804 pAdapterNode = pNext;
5805 }
5806 return TRUE;
5807}
5808
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08005809/* Decides whether to send suspend notification to Riva
5810 * if any adapter is in BMPS; then it is required */
5811v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
5812{
5813 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
5814 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5815
5816 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
5817 {
5818 return TRUE;
5819 }
5820 return FALSE;
5821}
5822
Jeff Johnson295189b2012-06-20 16:38:30 -07005823void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5824{
5825 switch(mode)
5826 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005827 case VOS_STA_MODE:
5828 case VOS_P2P_CLIENT_MODE:
5829 case VOS_P2P_GO_MODE:
5830 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07005831 pHddCtx->concurrency_mode |= (1 << mode);
5832 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07005833 break;
5834 default:
5835 break;
5836
5837 }
5838 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5839 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5840}
5841
5842
5843void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5844{
5845 switch(mode)
5846 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005847 case VOS_STA_MODE:
5848 case VOS_P2P_CLIENT_MODE:
5849 case VOS_P2P_GO_MODE:
5850 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005851 pHddCtx->no_of_sessions[mode]--;
5852 if (!(pHddCtx->no_of_sessions[mode]))
5853 pHddCtx->concurrency_mode &= (~(1 << mode));
5854 break;
5855 default:
5856 break;
5857 }
5858 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5859 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5860}
5861
Jeff Johnsone7245742012-09-05 17:12:55 -07005862/**---------------------------------------------------------------------------
5863 *
5864 * \brief wlan_hdd_restart_init
5865 *
5866 * This function initalizes restart timer/flag. An internal function.
5867 *
5868 * \param - pHddCtx
5869 *
5870 * \return - None
5871 *
5872 * --------------------------------------------------------------------------*/
5873
5874static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
5875{
5876 /* Initialize */
5877 pHddCtx->hdd_restart_retries = 0;
5878 atomic_set(&pHddCtx->isRestartInProgress, 0);
5879 vos_timer_init(&pHddCtx->hdd_restart_timer,
5880 VOS_TIMER_TYPE_SW,
5881 wlan_hdd_restart_timer_cb,
5882 pHddCtx);
5883}
5884/**---------------------------------------------------------------------------
5885 *
5886 * \brief wlan_hdd_restart_deinit
5887 *
5888 * This function cleans up the resources used. An internal function.
5889 *
5890 * \param - pHddCtx
5891 *
5892 * \return - None
5893 *
5894 * --------------------------------------------------------------------------*/
5895
5896static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
5897{
5898
5899 VOS_STATUS vos_status;
5900 /* Block any further calls */
5901 atomic_set(&pHddCtx->isRestartInProgress, 1);
5902 /* Cleanup */
5903 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
5904 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005905 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005906 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
5907 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005908 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005909
5910}
5911
5912/**---------------------------------------------------------------------------
5913 *
5914 * \brief wlan_hdd_framework_restart
5915 *
5916 * This function uses a cfg80211 API to start a framework initiated WLAN
5917 * driver module unload/load.
5918 *
5919 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
5920 *
5921 *
5922 * \param - pHddCtx
5923 *
5924 * \return - VOS_STATUS_SUCCESS: Success
5925 * VOS_STATUS_E_EMPTY: Adapter is Empty
5926 * VOS_STATUS_E_NOMEM: No memory
5927
5928 * --------------------------------------------------------------------------*/
5929
5930static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
5931{
5932 VOS_STATUS status = VOS_STATUS_SUCCESS;
5933 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5934 int len = (sizeof (struct ieee80211_mgmt));
5935 struct ieee80211_mgmt *mgmt = NULL;
5936
5937 /* Prepare the DEAUTH managment frame with reason code */
5938 mgmt = kzalloc(len, GFP_KERNEL);
5939 if(mgmt == NULL)
5940 {
5941 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1250df42012-12-10 14:31:52 -08005942 "%s: memory allocation failed (%d bytes)", __func__, len);
Jeff Johnsone7245742012-09-05 17:12:55 -07005943 return VOS_STATUS_E_NOMEM;
5944 }
5945 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
5946
5947 /* Iterate over all adapters/devices */
5948 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5949 do
5950 {
5951 if( (status == VOS_STATUS_SUCCESS) &&
5952 pAdapterNode &&
5953 pAdapterNode->pAdapter)
5954 {
5955 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5956 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
5957 pAdapterNode->pAdapter->dev->name,
5958 pAdapterNode->pAdapter->device_mode,
5959 pHddCtx->hdd_restart_retries + 1);
5960 /*
5961 * CFG80211 event to restart the driver
5962 *
5963 * 'cfg80211_send_unprot_deauth' sends a
5964 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
5965 * of SME(Linux Kernel) state machine.
5966 *
5967 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
5968 * the driver.
5969 *
5970 */
5971
5972 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
5973 }
5974 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5975 pAdapterNode = pNext;
5976 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
5977
5978
5979 /* Free the allocated management frame */
5980 kfree(mgmt);
5981
5982 /* Retry until we unload or reach max count */
5983 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
5984 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
5985
5986 return status;
5987
5988}
5989/**---------------------------------------------------------------------------
5990 *
5991 * \brief wlan_hdd_restart_timer_cb
5992 *
5993 * Restart timer callback. An internal function.
5994 *
5995 * \param - User data:
5996 *
5997 * \return - None
5998 *
5999 * --------------------------------------------------------------------------*/
6000
6001void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6002{
6003 hdd_context_t *pHddCtx = usrDataForCallback;
6004 wlan_hdd_framework_restart(pHddCtx);
6005 return;
6006
6007}
6008
6009
6010/**---------------------------------------------------------------------------
6011 *
6012 * \brief wlan_hdd_restart_driver
6013 *
6014 * This function sends an event to supplicant to restart the WLAN driver.
6015 *
6016 * This function is called from vos_wlanRestart.
6017 *
6018 * \param - pHddCtx
6019 *
6020 * \return - VOS_STATUS_SUCCESS: Success
6021 * VOS_STATUS_E_EMPTY: Adapter is Empty
6022 * VOS_STATUS_E_ALREADY: Request already in progress
6023
6024 * --------------------------------------------------------------------------*/
6025VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6026{
6027 VOS_STATUS status = VOS_STATUS_SUCCESS;
6028
6029 /* A tight check to make sure reentrancy */
6030 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6031 {
6032 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6033 "%s: WLAN restart is already in progress", __func__);
6034
6035 return VOS_STATUS_E_ALREADY;
6036 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006037 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006038#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006039 wcnss_reset_intr();
6040#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006041
Jeff Johnsone7245742012-09-05 17:12:55 -07006042 return status;
6043}
6044
6045
Jeff Johnson295189b2012-06-20 16:38:30 -07006046//Register the module init/exit functions
6047module_init(hdd_module_init);
6048module_exit(hdd_module_exit);
6049
6050MODULE_LICENSE("Dual BSD/GPL");
6051MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6052MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6053
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006054module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6055 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006056
Jeff Johnson76052702013-04-16 13:55:05 -07006057module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006058 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);