blob: 8801b7b11880c02211f43af78d77815ef34005b8 [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",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05301996 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07001997 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 "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302106 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002107 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
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002653static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07002654{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002655 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07002656
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002657 if (NULL == pAdapter)
2658 {
2659 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
2660 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07002661 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002662
2663 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2664 {
2665 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
2666 return eHAL_STATUS_NOT_INITIALIZED;
2667 }
2668
2669 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
2670
2671 /* need to make sure all of our scheduled work has completed.
2672 * This callback is called from MC thread context, so it is safe to
2673 * to call below flush workqueue API from here.
2674 */
2675 flush_scheduled_work();
2676
2677 /* We can be blocked while waiting for scheduled work to be
2678 * flushed, and the adapter structure can potentially be freed, in
2679 * which case the magic will have been reset. So make sure the
2680 * magic is still good, and hence the adapter structure is still
2681 * valid, before signaling completion */
2682 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
2683 {
2684 complete(&pAdapter->session_close_comp_var);
2685 }
2686
Jeff Johnson295189b2012-06-20 16:38:30 -07002687 return eHAL_STATUS_SUCCESS;
2688}
2689
2690VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
2691{
2692 struct net_device *pWlanDev = pAdapter->dev;
2693 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2694 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2695 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2696 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2697 int rc = 0;
2698
2699 INIT_COMPLETION(pAdapter->session_open_comp_var);
2700 //Open a SME session for future operation
2701 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
2702 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
2703 if ( !HAL_STATUS_SUCCESS( halStatus ) )
2704 {
2705 hddLog(VOS_TRACE_LEVEL_FATAL,
2706 "sme_OpenSession() failed with status code %08d [x%08lx]",
2707 halStatus, halStatus );
2708 status = VOS_STATUS_E_FAILURE;
2709 goto error_sme_open;
2710 }
2711
2712 //Block on a completion variable. Can't wait forever though.
2713 rc = wait_for_completion_interruptible_timeout(
2714 &pAdapter->session_open_comp_var,
2715 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2716 if (!rc)
2717 {
2718 hddLog(VOS_TRACE_LEVEL_FATAL,
2719 "Session is not opened within timeout period code %08d", rc );
2720 status = VOS_STATUS_E_FAILURE;
2721 goto error_sme_open;
2722 }
2723
2724 // Register wireless extensions
2725 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
2726 {
2727 hddLog(VOS_TRACE_LEVEL_FATAL,
2728 "hdd_register_wext() failed with status code %08d [x%08lx]",
2729 halStatus, halStatus );
2730 status = VOS_STATUS_E_FAILURE;
2731 goto error_register_wext;
2732 }
2733 //Safe to register the hard_start_xmit function again
2734#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2735 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
2736#else
2737 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
2738#endif
2739
2740 //Set the Connection State to Not Connected
2741 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2742
2743 //Set the default operation channel
2744 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
2745
2746 /* Make the default Auth Type as OPEN*/
2747 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2748
2749 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
2750 {
2751 hddLog(VOS_TRACE_LEVEL_FATAL,
2752 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
2753 status, status );
2754 goto error_init_txrx;
2755 }
2756
2757 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2758
2759 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
2760 {
2761 hddLog(VOS_TRACE_LEVEL_FATAL,
2762 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
2763 status, status );
2764 goto error_wmm_init;
2765 }
2766
2767 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2768
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002769#ifdef FEATURE_WLAN_TDLS
2770 if(0 != wlan_hdd_tdls_init(pAdapter))
2771 {
2772 status = VOS_STATUS_E_FAILURE;
2773 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
2774 goto error_tdls_init;
2775 }
2776 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2777#endif
2778
Jeff Johnson295189b2012-06-20 16:38:30 -07002779 return VOS_STATUS_SUCCESS;
2780
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002781#ifdef FEATURE_WLAN_TDLS
2782error_tdls_init:
2783 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2784 hdd_wmm_adapter_close(pAdapter);
2785#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002786error_wmm_init:
2787 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2788 hdd_deinit_tx_rx(pAdapter);
2789error_init_txrx:
2790 hdd_UnregisterWext(pWlanDev);
2791error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002792 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07002793 {
2794 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002795 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002796 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002797 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07002798 {
2799 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002800 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07002801 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002802 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07002803 }
2804}
2805error_sme_open:
2806 return status;
2807}
2808
Jeff Johnson295189b2012-06-20 16:38:30 -07002809void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2810{
2811 hdd_cfg80211_state_t *cfgState;
2812
2813 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
2814
2815 if( NULL != cfgState->buf )
2816 {
2817 int rc;
2818 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
2819 rc = wait_for_completion_interruptible_timeout(
2820 &pAdapter->tx_action_cnf_event,
2821 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2822 if(!rc)
2823 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08002824 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07002825 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
2826 }
2827 }
2828 return;
2829}
Jeff Johnson295189b2012-06-20 16:38:30 -07002830
2831void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2832{
2833 ENTER();
2834 switch ( pAdapter->device_mode )
2835 {
2836 case WLAN_HDD_INFRA_STATION:
2837 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002838 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002839 {
2840 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2841 {
2842 hdd_deinit_tx_rx( pAdapter );
2843 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2844 }
2845
2846 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
2847 {
2848 hdd_wmm_adapter_close( pAdapter );
2849 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2850 }
2851
Jeff Johnson295189b2012-06-20 16:38:30 -07002852 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002853#ifdef FEATURE_WLAN_TDLS
2854 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
2855 {
2856 wlan_hdd_tdls_exit(pAdapter);
2857 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2858 }
2859#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002860
2861 break;
2862 }
2863
2864 case WLAN_HDD_SOFTAP:
2865 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002866 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002867 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002868
2869 hdd_unregister_hostapd(pAdapter);
2870 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07002871 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07002872 break;
2873 }
2874
2875 case WLAN_HDD_MONITOR:
2876 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002877 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07002878 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2879 {
2880 hdd_deinit_tx_rx( pAdapter );
2881 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2882 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002883 if(NULL != pAdapterforTx)
2884 {
2885 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
2886 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002887 break;
2888 }
2889
2890
2891 default:
2892 break;
2893 }
2894
2895 EXIT();
2896}
2897
2898void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
2899{
2900 struct net_device *pWlanDev = pAdapter->dev;
2901
2902 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
2903 if( rtnl_held )
2904 {
2905 unregister_netdevice(pWlanDev);
2906 }
2907 else
2908 {
2909 unregister_netdev(pWlanDev);
2910 }
2911 // note that the pAdapter is no longer valid at this point
2912 // since the memory has been reclaimed
2913 }
2914
2915}
2916
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08002917void hdd_set_pwrparams(hdd_context_t *pHddCtx)
2918{
2919 tSirSetPowerParamsReq powerRequest = { 0 };
2920
2921 powerRequest.uIgnoreDTIM = 1;
2922
2923 if (pHddCtx->cfg_ini->enableModulatedDTIM)
2924 {
2925 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
2926 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2927 }
2928 else
2929 {
2930 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
2931 }
2932
2933 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
2934 *specified during Enter/Exit BMPS when LCD off*/
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 /* switch to the DTIM specified in cfg.ini */
2941 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2942 "Switch to DTIM%d", powerRequest.uListenInterval);
2943 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2944
2945}
2946
2947void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
2948{
2949 /*Switch back to DTIM 1*/
2950 tSirSetPowerParamsReq powerRequest = { 0 };
2951
2952 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
2953 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2954
2955 /* Update ignoreDTIM and ListedInterval in CFG with default values */
2956 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2957 NULL, eANI_BOOLEAN_FALSE);
2958 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2959 NULL, eANI_BOOLEAN_FALSE);
2960
2961 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2962 "Switch to DTIM%d",powerRequest.uListenInterval);
2963 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2964
2965}
2966
Jeff Johnson295189b2012-06-20 16:38:30 -07002967VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
2968{
2969 VOS_STATUS status = VOS_STATUS_SUCCESS;
2970
2971 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2972 {
2973 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2974 }
2975
2976 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2977 {
2978 sme_StartAutoBmpsTimer(pHddCtx->hHal);
2979 }
2980
2981 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2982 {
2983 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2984 }
2985
2986 return status;
2987}
2988
2989VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
2990{
2991 hdd_adapter_t *pAdapter = NULL;
2992 eHalStatus halStatus;
2993 VOS_STATUS status = VOS_STATUS_E_INVAL;
2994 v_BOOL_t disableBmps = FALSE;
2995 v_BOOL_t disableImps = FALSE;
2996
2997 switch(session_type)
2998 {
2999 case WLAN_HDD_INFRA_STATION:
3000 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003001 case WLAN_HDD_P2P_CLIENT:
3002 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003003 //Exit BMPS -> Is Sta/P2P Client is already connected
3004 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3005 if((NULL != pAdapter)&&
3006 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3007 {
3008 disableBmps = TRUE;
3009 }
3010
3011 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3012 if((NULL != pAdapter)&&
3013 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3014 {
3015 disableBmps = TRUE;
3016 }
3017
3018 //Exit both Bmps and Imps incase of Go/SAP Mode
3019 if((WLAN_HDD_SOFTAP == session_type) ||
3020 (WLAN_HDD_P2P_GO == session_type))
3021 {
3022 disableBmps = TRUE;
3023 disableImps = TRUE;
3024 }
3025
3026 if(TRUE == disableImps)
3027 {
3028 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3029 {
3030 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3031 }
3032 }
3033
3034 if(TRUE == disableBmps)
3035 {
3036 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3037 {
3038 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3039
3040 if(eHAL_STATUS_SUCCESS != halStatus)
3041 {
3042 status = VOS_STATUS_E_FAILURE;
3043 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3044 VOS_ASSERT(0);
3045 return status;
3046 }
3047 }
3048
3049 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3050 {
3051 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3052
3053 if(eHAL_STATUS_SUCCESS != halStatus)
3054 {
3055 status = VOS_STATUS_E_FAILURE;
3056 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3057 VOS_ASSERT(0);
3058 return status;
3059 }
3060 }
3061 }
3062
3063 if((TRUE == disableBmps) ||
3064 (TRUE == disableImps))
3065 {
3066 /* Now, get the chip into Full Power now */
3067 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3068 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3069 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3070
3071 if(halStatus != eHAL_STATUS_SUCCESS)
3072 {
3073 if(halStatus == eHAL_STATUS_PMC_PENDING)
3074 {
3075 //Block on a completion variable. Can't wait forever though
3076 wait_for_completion_interruptible_timeout(
3077 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3078 }
3079 else
3080 {
3081 status = VOS_STATUS_E_FAILURE;
3082 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3083 VOS_ASSERT(0);
3084 return status;
3085 }
3086 }
3087
3088 status = VOS_STATUS_SUCCESS;
3089 }
3090
3091 break;
3092 }
3093 return status;
3094}
3095
3096hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003097 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003098 tANI_U8 rtnl_held )
3099{
3100 hdd_adapter_t *pAdapter = NULL;
3101 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3102 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3103 VOS_STATUS exitbmpsStatus;
3104
3105 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3106
3107 //Disable BMPS incase of Concurrency
3108 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3109
3110 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3111 {
3112 //Fail to Exit BMPS
3113 VOS_ASSERT(0);
3114 return NULL;
3115 }
3116
3117 switch(session_type)
3118 {
3119 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003120 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003121 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003122 {
3123 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3124
3125 if( NULL == pAdapter )
3126 return NULL;
3127
Jeff Johnsone7245742012-09-05 17:12:55 -07003128 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3129 NL80211_IFTYPE_P2P_CLIENT:
3130 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003131
Jeff Johnson295189b2012-06-20 16:38:30 -07003132 pAdapter->device_mode = session_type;
3133
3134 status = hdd_init_station_mode( pAdapter );
3135 if( VOS_STATUS_SUCCESS != status )
3136 goto err_free_netdev;
3137
3138 status = hdd_register_interface( pAdapter, rtnl_held );
3139 if( VOS_STATUS_SUCCESS != status )
3140 {
3141 hdd_deinit_adapter(pHddCtx, pAdapter);
3142 goto err_free_netdev;
3143 }
3144 //Stop the Interface TX queue.
3145 netif_tx_disable(pAdapter->dev);
3146 //netif_tx_disable(pWlanDev);
3147 netif_carrier_off(pAdapter->dev);
3148
3149 break;
3150 }
3151
Jeff Johnson295189b2012-06-20 16:38:30 -07003152 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003153 case WLAN_HDD_SOFTAP:
3154 {
3155 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3156 if( NULL == pAdapter )
3157 return NULL;
3158
Jeff Johnson295189b2012-06-20 16:38:30 -07003159 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3160 NL80211_IFTYPE_AP:
3161 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003162 pAdapter->device_mode = session_type;
3163
3164 status = hdd_init_ap_mode(pAdapter);
3165 if( VOS_STATUS_SUCCESS != status )
3166 goto err_free_netdev;
3167
3168 status = hdd_register_hostapd( pAdapter, rtnl_held );
3169 if( VOS_STATUS_SUCCESS != status )
3170 {
3171 hdd_deinit_adapter(pHddCtx, pAdapter);
3172 goto err_free_netdev;
3173 }
3174
3175 netif_tx_disable(pAdapter->dev);
3176 netif_carrier_off(pAdapter->dev);
3177
3178 hdd_set_conparam( 1 );
3179 break;
3180 }
3181 case WLAN_HDD_MONITOR:
3182 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003183 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3184 if( NULL == pAdapter )
3185 return NULL;
3186
3187 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3188 pAdapter->device_mode = session_type;
3189 status = hdd_register_interface( pAdapter, rtnl_held );
3190#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3191 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3192#else
3193 pAdapter->dev->open = hdd_mon_open;
3194 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3195#endif
3196 hdd_init_tx_rx( pAdapter );
3197 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3198 //Set adapter to be used for data tx. It will use either GO or softap.
3199 pAdapter->sessionCtx.monitor.pAdapterForTx =
3200 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003201 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3202 {
3203 pAdapter->sessionCtx.monitor.pAdapterForTx =
3204 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3205 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003206 /* This workqueue will be used to transmit management packet over
3207 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003208 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3209 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3210 return NULL;
3211 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003212
Jeff Johnson295189b2012-06-20 16:38:30 -07003213 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3214 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003215 }
3216 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003217 case WLAN_HDD_FTM:
3218 {
3219 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3220
3221 if( NULL == pAdapter )
3222 return NULL;
3223 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3224 * message while loading driver in FTM mode. */
3225 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3226 pAdapter->device_mode = session_type;
3227 status = hdd_register_interface( pAdapter, rtnl_held );
3228 }
3229 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003230 default:
3231 {
3232 VOS_ASSERT(0);
3233 return NULL;
3234 }
3235 }
3236
3237
3238 if( VOS_STATUS_SUCCESS == status )
3239 {
3240 //Add it to the hdd's session list.
3241 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3242 if( NULL == pHddAdapterNode )
3243 {
3244 status = VOS_STATUS_E_NOMEM;
3245 }
3246 else
3247 {
3248 pHddAdapterNode->pAdapter = pAdapter;
3249 status = hdd_add_adapter_back ( pHddCtx,
3250 pHddAdapterNode );
3251 }
3252 }
3253
3254 if( VOS_STATUS_SUCCESS != status )
3255 {
3256 if( NULL != pAdapter )
3257 {
3258 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3259 pAdapter = NULL;
3260 }
3261 if( NULL != pHddAdapterNode )
3262 {
3263 vos_mem_free( pHddAdapterNode );
3264 }
3265
3266 goto resume_bmps;
3267 }
3268
3269 if(VOS_STATUS_SUCCESS == status)
3270 {
3271 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3272
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003273 //Initialize the WoWL service
3274 if(!hdd_init_wowl(pAdapter))
3275 {
3276 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3277 goto err_free_netdev;
3278 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003279 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003280 return pAdapter;
3281
3282err_free_netdev:
3283 free_netdev(pAdapter->dev);
3284 wlan_hdd_release_intf_addr( pHddCtx,
3285 pAdapter->macAddressCurrent.bytes );
3286
3287resume_bmps:
3288 //If bmps disabled enable it
3289 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3290 {
3291 hdd_enable_bmps_imps(pHddCtx);
3292 }
3293 return NULL;
3294}
3295
3296VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3297 tANI_U8 rtnl_held )
3298{
3299 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3300 VOS_STATUS status;
3301
3302 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3303 if( VOS_STATUS_SUCCESS != status )
3304 return status;
3305
3306 while ( pCurrent->pAdapter != pAdapter )
3307 {
3308 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3309 if( VOS_STATUS_SUCCESS != status )
3310 break;
3311
3312 pCurrent = pNext;
3313 }
3314 pAdapterNode = pCurrent;
3315 if( VOS_STATUS_SUCCESS == status )
3316 {
3317 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3318 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3319 hdd_remove_adapter( pHddCtx, pAdapterNode );
3320 vos_mem_free( pAdapterNode );
3321
Jeff Johnson295189b2012-06-20 16:38:30 -07003322
3323 /* If there is a single session of STA/P2P client, re-enable BMPS */
3324 if ((!vos_concurrent_sessions_running()) &&
3325 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3326 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3327 {
3328 hdd_enable_bmps_imps(pHddCtx);
3329 }
3330
3331 return VOS_STATUS_SUCCESS;
3332 }
3333
3334 return VOS_STATUS_E_FAILURE;
3335}
3336
3337VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3338{
3339 hdd_adapter_list_node_t *pHddAdapterNode;
3340 VOS_STATUS status;
3341
3342 ENTER();
3343
3344 do
3345 {
3346 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3347 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3348 {
3349 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3350 vos_mem_free( pHddAdapterNode );
3351 }
3352 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3353
3354 EXIT();
3355
3356 return VOS_STATUS_SUCCESS;
3357}
3358
3359void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3360{
3361 v_U8_t addIE[1] = {0};
3362
3363 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3364 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3365 eANI_BOOLEAN_FALSE) )
3366 {
3367 hddLog(LOGE,
3368 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3369 }
3370
3371 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3372 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3373 eANI_BOOLEAN_FALSE) )
3374 {
3375 hddLog(LOGE,
3376 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3377 }
3378
3379 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3380 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3381 eANI_BOOLEAN_FALSE) )
3382 {
3383 hddLog(LOGE,
3384 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3385 }
3386}
3387
3388VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3389{
3390 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3391 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3392 union iwreq_data wrqu;
3393
3394 ENTER();
3395
3396 switch(pAdapter->device_mode)
3397 {
3398 case WLAN_HDD_INFRA_STATION:
3399 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003400 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003401 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3402 {
3403 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3404 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3405 pAdapter->sessionId,
3406 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3407 else
3408 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3409 pAdapter->sessionId,
3410 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3411 //success implies disconnect command got queued up successfully
3412 if(halStatus == eHAL_STATUS_SUCCESS)
3413 {
3414 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3415 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3416 }
3417 memset(&wrqu, '\0', sizeof(wrqu));
3418 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3419 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3420 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3421 }
3422 else
3423 {
3424 hdd_abort_mac_scan(pHddCtx);
3425 }
3426
3427 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3428 {
3429 INIT_COMPLETION(pAdapter->session_close_comp_var);
3430 if (eHAL_STATUS_SUCCESS ==
3431 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3432 hdd_smeCloseSessionCallback, pAdapter))
3433 {
3434 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003435 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003436 &pAdapter->session_close_comp_var,
3437 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3438 }
3439 }
3440
3441 break;
3442
3443 case WLAN_HDD_SOFTAP:
3444 case WLAN_HDD_P2P_GO:
3445 //Any softap specific cleanup here...
3446 mutex_lock(&pHddCtx->sap_lock);
3447 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3448 {
3449 VOS_STATUS status;
3450 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3451
3452 //Stop Bss.
3453 status = WLANSAP_StopBss(pHddCtx->pvosContext);
3454 if (VOS_IS_STATUS_SUCCESS(status))
3455 {
3456 hdd_hostapd_state_t *pHostapdState =
3457 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3458
3459 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
3460
3461 if (!VOS_IS_STATUS_SUCCESS(status))
3462 {
3463 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003464 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003465 }
3466 }
3467 else
3468 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003469 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003470 }
3471 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
3472
3473 if (eHAL_STATUS_FAILURE ==
3474 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
3475 0, NULL, eANI_BOOLEAN_FALSE))
3476 {
3477 hddLog(LOGE,
3478 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003479 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003480 }
3481
3482 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
3483 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
3484 eANI_BOOLEAN_FALSE) )
3485 {
3486 hddLog(LOGE,
3487 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
3488 }
3489
3490 // Reset WNI_CFG_PROBE_RSP Flags
3491 wlan_hdd_reset_prob_rspies(pAdapter);
3492 kfree(pAdapter->sessionCtx.ap.beacon);
3493 pAdapter->sessionCtx.ap.beacon = NULL;
3494 }
3495 mutex_unlock(&pHddCtx->sap_lock);
3496 break;
3497 case WLAN_HDD_MONITOR:
3498 break;
3499 default:
3500 break;
3501 }
3502
3503 EXIT();
3504 return VOS_STATUS_SUCCESS;
3505}
3506
3507VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
3508{
3509 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3510 VOS_STATUS status;
3511 hdd_adapter_t *pAdapter;
3512
3513 ENTER();
3514
3515 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3516
3517 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3518 {
3519 pAdapter = pAdapterNode->pAdapter;
3520 netif_tx_disable(pAdapter->dev);
3521 netif_carrier_off(pAdapter->dev);
3522
3523 hdd_stop_adapter( pHddCtx, pAdapter );
3524
3525 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3526 pAdapterNode = pNext;
3527 }
3528
3529 EXIT();
3530
3531 return VOS_STATUS_SUCCESS;
3532}
3533
3534VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
3535{
3536 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3537 VOS_STATUS status;
3538 hdd_adapter_t *pAdapter;
3539
3540 ENTER();
3541
3542 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3543
3544 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3545 {
3546 pAdapter = pAdapterNode->pAdapter;
3547 netif_tx_disable(pAdapter->dev);
3548 netif_carrier_off(pAdapter->dev);
3549
3550 //Record whether STA is associated
3551 pAdapter->sessionCtx.station.bSendDisconnect =
3552 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
3553 VOS_TRUE : VOS_FALSE;
3554
3555 hdd_deinit_tx_rx(pAdapter);
3556 hdd_wmm_adapter_close(pAdapter);
3557
3558 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3559 pAdapterNode = pNext;
3560 }
3561
3562 EXIT();
3563
3564 return VOS_STATUS_SUCCESS;
3565}
3566
3567VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
3568{
3569 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3570 VOS_STATUS status;
3571 hdd_adapter_t *pAdapter;
3572 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
3573
3574 ENTER();
3575
3576 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3577
3578 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3579 {
3580 pAdapter = pAdapterNode->pAdapter;
3581
3582 switch(pAdapter->device_mode)
3583 {
3584 case WLAN_HDD_INFRA_STATION:
3585 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003586 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003587 hdd_init_station_mode(pAdapter);
3588 /* Open the gates for HDD to receive Wext commands */
3589 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003590 pHddCtx->scan_info.mScanPending = FALSE;
3591 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003592
3593 //Trigger the initial scan
3594 hdd_wlan_initial_scan(pAdapter);
3595
3596 //Indicate disconnect event to supplicant if associated previously
3597 if(pAdapter->sessionCtx.station.bSendDisconnect)
3598 {
3599 union iwreq_data wrqu;
3600 memset(&wrqu, '\0', sizeof(wrqu));
3601 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3602 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3603 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3604 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
3605
Jeff Johnson295189b2012-06-20 16:38:30 -07003606 /* indicate disconnected event to nl80211 */
3607 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
3608 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003609 }
3610 break;
3611
3612 case WLAN_HDD_SOFTAP:
3613 /* softAP can handle SSR */
3614 break;
3615
3616 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003617 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
3618 __func__);
3619 /* event supplicant to restart */
3620 cfg80211_del_sta(pAdapter->dev,
3621 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003622 break;
3623
3624 case WLAN_HDD_MONITOR:
3625 /* monitor interface start */
3626 break;
3627 default:
3628 break;
3629 }
3630
3631 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3632 pAdapterNode = pNext;
3633 }
3634
3635 EXIT();
3636
3637 return VOS_STATUS_SUCCESS;
3638}
3639
3640VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
3641{
3642 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3643 hdd_adapter_t *pAdapter;
3644 VOS_STATUS status;
3645 v_U32_t roamId;
3646
3647 ENTER();
3648
3649 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3650
3651 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3652 {
3653 pAdapter = pAdapterNode->pAdapter;
3654
3655 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3656 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
3657 {
3658 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3659 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3660
3661 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3662 init_completion(&pAdapter->disconnect_comp_var);
3663 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
3664 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3665
3666 wait_for_completion_interruptible_timeout(
3667 &pAdapter->disconnect_comp_var,
3668 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3669
3670 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
3671 pHddCtx->isAmpAllowed = VOS_FALSE;
3672 sme_RoamConnect(pHddCtx->hHal,
3673 pAdapter->sessionId, &(pWextState->roamProfile),
3674 &roamId);
3675 }
3676
3677 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3678 pAdapterNode = pNext;
3679 }
3680
3681 EXIT();
3682
3683 return VOS_STATUS_SUCCESS;
3684}
3685
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07003686void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
3687{
3688 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3689 VOS_STATUS status;
3690 hdd_adapter_t *pAdapter;
3691 hdd_station_ctx_t *pHddStaCtx;
3692 hdd_ap_ctx_t *pHddApCtx;
3693 hdd_hostapd_state_t * pHostapdState;
3694 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
3695 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
3696 const char *p2pMode = "DEV";
3697 const char *ccMode = "Standalone";
3698 int n;
3699
3700 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3701 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3702 {
3703 pAdapter = pAdapterNode->pAdapter;
3704 switch (pAdapter->device_mode) {
3705 case WLAN_HDD_INFRA_STATION:
3706 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3707 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3708 staChannel = pHddStaCtx->conn_info.operationChannel;
3709 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
3710 }
3711 break;
3712 case WLAN_HDD_P2P_CLIENT:
3713 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3714 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3715 p2pChannel = pHddStaCtx->conn_info.operationChannel;
3716 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
3717 p2pMode = "CLI";
3718 }
3719 break;
3720 case WLAN_HDD_P2P_GO:
3721 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3722 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3723 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3724 p2pChannel = pHddApCtx->operatingChannel;
3725 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
3726 }
3727 p2pMode = "GO";
3728 break;
3729 case WLAN_HDD_SOFTAP:
3730 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3731 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3732 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3733 apChannel = pHddApCtx->operatingChannel;
3734 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
3735 }
3736 break;
3737 default:
3738 break;
3739 }
3740 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3741 pAdapterNode = pNext;
3742 }
3743 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
3744 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
3745 }
3746 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
3747 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
3748 if (p2pChannel > 0) {
3749 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
3750 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
3751 }
3752 if (apChannel > 0) {
3753 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
3754 apChannel, MAC_ADDR_ARRAY(apBssid));
3755 }
3756
3757 if (p2pChannel > 0 && apChannel > 0) {
3758 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
3759 }
3760}
3761
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003762bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07003763{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003764 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07003765}
3766
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003767/* Once SSR is disabled then it cannot be set. */
3768void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07003769{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003770 if (HDD_SSR_DISABLED == isSsrRequired)
3771 return;
3772
Jeff Johnson295189b2012-06-20 16:38:30 -07003773 isSsrRequired = value;
3774}
3775
3776VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
3777 hdd_adapter_list_node_t** ppAdapterNode)
3778{
3779 VOS_STATUS status;
3780 spin_lock(&pHddCtx->hddAdapters.lock);
3781 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
3782 (hdd_list_node_t**) ppAdapterNode );
3783 spin_unlock(&pHddCtx->hddAdapters.lock);
3784 return status;
3785}
3786
3787VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
3788 hdd_adapter_list_node_t* pAdapterNode,
3789 hdd_adapter_list_node_t** pNextAdapterNode)
3790{
3791 VOS_STATUS status;
3792 spin_lock(&pHddCtx->hddAdapters.lock);
3793 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
3794 (hdd_list_node_t*) pAdapterNode,
3795 (hdd_list_node_t**)pNextAdapterNode );
3796
3797 spin_unlock(&pHddCtx->hddAdapters.lock);
3798 return status;
3799}
3800
3801VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
3802 hdd_adapter_list_node_t* pAdapterNode)
3803{
3804 VOS_STATUS status;
3805 spin_lock(&pHddCtx->hddAdapters.lock);
3806 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
3807 &pAdapterNode->node );
3808 spin_unlock(&pHddCtx->hddAdapters.lock);
3809 return status;
3810}
3811
3812VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
3813 hdd_adapter_list_node_t** ppAdapterNode)
3814{
3815 VOS_STATUS status;
3816 spin_lock(&pHddCtx->hddAdapters.lock);
3817 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
3818 (hdd_list_node_t**) ppAdapterNode );
3819 spin_unlock(&pHddCtx->hddAdapters.lock);
3820 return status;
3821}
3822
3823VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
3824 hdd_adapter_list_node_t* pAdapterNode)
3825{
3826 VOS_STATUS status;
3827 spin_lock(&pHddCtx->hddAdapters.lock);
3828 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
3829 (hdd_list_node_t*) pAdapterNode );
3830 spin_unlock(&pHddCtx->hddAdapters.lock);
3831 return status;
3832}
3833
3834VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
3835 hdd_adapter_list_node_t* pAdapterNode)
3836{
3837 VOS_STATUS status;
3838 spin_lock(&pHddCtx->hddAdapters.lock);
3839 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
3840 (hdd_list_node_t*) pAdapterNode );
3841 spin_unlock(&pHddCtx->hddAdapters.lock);
3842 return status;
3843}
3844
3845hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
3846 tSirMacAddr macAddr )
3847{
3848 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3849 hdd_adapter_t *pAdapter;
3850 VOS_STATUS status;
3851
3852 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3853
3854 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3855 {
3856 pAdapter = pAdapterNode->pAdapter;
3857
3858 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
3859 macAddr, sizeof(tSirMacAddr) ) )
3860 {
3861 return pAdapter;
3862 }
3863 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3864 pAdapterNode = pNext;
3865 }
3866
3867 return NULL;
3868
3869}
3870
3871hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
3872{
3873 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3874 hdd_adapter_t *pAdapter;
3875 VOS_STATUS status;
3876
3877 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3878
3879 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3880 {
3881 pAdapter = pAdapterNode->pAdapter;
3882
3883 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
3884 IFNAMSIZ ) )
3885 {
3886 return pAdapter;
3887 }
3888 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3889 pAdapterNode = pNext;
3890 }
3891
3892 return NULL;
3893
3894}
3895
3896hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
3897{
3898 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3899 hdd_adapter_t *pAdapter;
3900 VOS_STATUS status;
3901
3902 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3903
3904 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3905 {
3906 pAdapter = pAdapterNode->pAdapter;
3907
3908 if( pAdapter && (mode == pAdapter->device_mode) )
3909 {
3910 return pAdapter;
3911 }
3912 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3913 pAdapterNode = pNext;
3914 }
3915
3916 return NULL;
3917
3918}
3919
3920//Remove this function later
3921hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
3922{
3923 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3924 hdd_adapter_t *pAdapter;
3925 VOS_STATUS status;
3926
3927 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3928
3929 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3930 {
3931 pAdapter = pAdapterNode->pAdapter;
3932
3933 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
3934 {
3935 return pAdapter;
3936 }
3937
3938 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3939 pAdapterNode = pNext;
3940 }
3941
3942 return NULL;
3943
3944}
3945
Jeff Johnson295189b2012-06-20 16:38:30 -07003946/**---------------------------------------------------------------------------
3947
3948 \brief hdd_set_monitor_tx_adapter() -
3949
3950 This API initializes the adapter to be used while transmitting on monitor
3951 adapter.
3952
3953 \param - pHddCtx - Pointer to the HDD context.
3954 pAdapter - Adapter that will used for TX. This can be NULL.
3955 \return - None.
3956 --------------------------------------------------------------------------*/
3957void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3958{
3959 hdd_adapter_t *pMonAdapter;
3960
3961 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
3962
3963 if( NULL != pMonAdapter )
3964 {
3965 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
3966 }
3967}
Jeff Johnson295189b2012-06-20 16:38:30 -07003968/**---------------------------------------------------------------------------
3969
3970 \brief hdd_select_queue() -
3971
3972 This API returns the operating channel of the requested device mode
3973
3974 \param - pHddCtx - Pointer to the HDD context.
3975 - mode - Device mode for which operating channel is required
3976 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
3977 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
3978 \return - channel number. "0" id the requested device is not found OR it is not connected.
3979 --------------------------------------------------------------------------*/
3980v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
3981{
3982 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3983 VOS_STATUS status;
3984 hdd_adapter_t *pAdapter;
3985 v_U8_t operatingChannel = 0;
3986
3987 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3988
3989 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3990 {
3991 pAdapter = pAdapterNode->pAdapter;
3992
3993 if( mode == pAdapter->device_mode )
3994 {
3995 switch(pAdapter->device_mode)
3996 {
3997 case WLAN_HDD_INFRA_STATION:
3998 case WLAN_HDD_P2P_CLIENT:
3999 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4000 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4001 break;
4002 case WLAN_HDD_SOFTAP:
4003 case WLAN_HDD_P2P_GO:
4004 /*softap connection info */
4005 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4006 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4007 break;
4008 default:
4009 break;
4010 }
4011
4012 break; //Found the device of interest. break the loop
4013 }
4014
4015 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4016 pAdapterNode = pNext;
4017 }
4018 return operatingChannel;
4019}
4020
4021#ifdef WLAN_FEATURE_PACKET_FILTERING
4022/**---------------------------------------------------------------------------
4023
4024 \brief hdd_set_multicast_list() -
4025
4026 This used to set the multicast address list.
4027
4028 \param - dev - Pointer to the WLAN device.
4029 - skb - Pointer to OS packet (sk_buff).
4030 \return - success/fail
4031
4032 --------------------------------------------------------------------------*/
4033static void hdd_set_multicast_list(struct net_device *dev)
4034{
4035 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004036 int mc_count;
4037 int i = 0;
4038 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304039
4040 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004041 {
4042 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304043 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004044 return;
4045 }
4046
4047 if (dev->flags & IFF_ALLMULTI)
4048 {
4049 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004050 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304051 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004052 }
4053 else
4054 {
4055 mc_count = netdev_mc_count(dev);
4056 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004057 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004058 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4059 {
4060 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004061 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304062 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004063 return;
4064 }
4065
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304066 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004067
4068 netdev_for_each_mc_addr(ha, dev) {
4069 if (i == mc_count)
4070 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304071 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4072 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4073 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004074 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304075 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004076 i++;
4077 }
4078 }
4079 return;
4080}
4081#endif
4082
4083/**---------------------------------------------------------------------------
4084
4085 \brief hdd_select_queue() -
4086
4087 This function is registered with the Linux OS for network
4088 core to decide which queue to use first.
4089
4090 \param - dev - Pointer to the WLAN device.
4091 - skb - Pointer to OS packet (sk_buff).
4092 \return - ac, Queue Index/access category corresponding to UP in IP header
4093
4094 --------------------------------------------------------------------------*/
4095v_U16_t hdd_select_queue(struct net_device *dev,
4096 struct sk_buff *skb)
4097{
4098 return hdd_wmm_select_queue(dev, skb);
4099}
4100
4101
4102/**---------------------------------------------------------------------------
4103
4104 \brief hdd_wlan_initial_scan() -
4105
4106 This function triggers the initial scan
4107
4108 \param - pAdapter - Pointer to the HDD adapter.
4109
4110 --------------------------------------------------------------------------*/
4111void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4112{
4113 tCsrScanRequest scanReq;
4114 tCsrChannelInfo channelInfo;
4115 eHalStatus halStatus;
4116 unsigned long scanId;
4117 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4118
4119 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4120 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4121 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4122
4123 if(sme_Is11dSupported(pHddCtx->hHal))
4124 {
4125 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4126 if ( HAL_STATUS_SUCCESS( halStatus ) )
4127 {
4128 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4129 if( !scanReq.ChannelInfo.ChannelList )
4130 {
4131 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4132 vos_mem_free(channelInfo.ChannelList);
4133 return;
4134 }
4135 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4136 channelInfo.numOfChannels);
4137 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4138 vos_mem_free(channelInfo.ChannelList);
4139 }
4140
4141 scanReq.scanType = eSIR_PASSIVE_SCAN;
4142 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4143 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4144 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4145 }
4146 else
4147 {
4148 scanReq.scanType = eSIR_ACTIVE_SCAN;
4149 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4150 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4151 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4152 }
4153
4154 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4155 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4156 {
4157 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4158 __func__, halStatus );
4159 }
4160
4161 if(sme_Is11dSupported(pHddCtx->hHal))
4162 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4163}
4164
4165struct fullPowerContext
4166{
4167 struct completion completion;
4168 unsigned int magic;
4169};
4170#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4171
4172/**---------------------------------------------------------------------------
4173
4174 \brief hdd_full_power_callback() - HDD full power callback function
4175
4176 This is the function invoked by SME to inform the result of a full power
4177 request issued by HDD
4178
4179 \param - callbackcontext - Pointer to cookie
4180 \param - status - result of request
4181
4182 \return - None
4183
4184 --------------------------------------------------------------------------*/
4185static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4186{
4187 struct fullPowerContext *pContext = callbackContext;
4188
4189 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304190 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004191
4192 if (NULL == callbackContext)
4193 {
4194 hddLog(VOS_TRACE_LEVEL_ERROR,
4195 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004196 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004197 return;
4198 }
4199
4200 /* there is a race condition that exists between this callback function
4201 and the caller since the caller could time out either before or
4202 while this code is executing. we'll assume the timeout hasn't
4203 occurred, but we'll verify that right before we save our work */
4204
4205 if (POWER_CONTEXT_MAGIC != pContext->magic)
4206 {
4207 /* the caller presumably timed out so there is nothing we can do */
4208 hddLog(VOS_TRACE_LEVEL_WARN,
4209 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004210 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004211 return;
4212 }
4213
4214 /* the race is on. caller could have timed out immediately after
4215 we verified the magic, but if so, caller will wait a short time
4216 for us to notify the caller, so the context will stay valid */
4217 complete(&pContext->completion);
4218}
4219
4220/**---------------------------------------------------------------------------
4221
4222 \brief hdd_wlan_exit() - HDD WLAN exit function
4223
4224 This is the driver exit point (invoked during rmmod)
4225
4226 \param - pHddCtx - Pointer to the HDD Context
4227
4228 \return - None
4229
4230 --------------------------------------------------------------------------*/
4231void hdd_wlan_exit(hdd_context_t *pHddCtx)
4232{
4233 eHalStatus halStatus;
4234 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4235 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304236 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004237 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004238 struct fullPowerContext powerContext;
4239 long lrc;
4240
4241 ENTER();
4242
Jeff Johnson88ba7742013-02-27 14:36:02 -08004243 if (VOS_FTM_MODE != hdd_get_conparam())
4244 {
4245 // Unloading, restart logic is no more required.
4246 wlan_hdd_restart_deinit(pHddCtx);
4247 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004248
Jeff Johnson295189b2012-06-20 16:38:30 -07004249 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004250 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004251 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004252 {
4253 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4254 WLAN_HDD_INFRA_STATION);
4255 if (pAdapter == NULL)
4256 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4257
4258 if (pAdapter != NULL)
4259 {
4260 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4261 hdd_UnregisterWext(pAdapter->dev);
4262 }
4263 }
4264 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004265
Jeff Johnson295189b2012-06-20 16:38:30 -07004266 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004267 {
4268 wlan_hdd_ftm_close(pHddCtx);
4269 goto free_hdd_ctx;
4270 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004271 //Stop the Interface TX queue.
4272 //netif_tx_disable(pWlanDev);
4273 //netif_carrier_off(pWlanDev);
4274
Jeff Johnson295189b2012-06-20 16:38:30 -07004275 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4276 {
4277 pAdapter = hdd_get_adapter(pHddCtx,
4278 WLAN_HDD_SOFTAP);
4279 }
4280 else
4281 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004282 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004283 {
4284 pAdapter = hdd_get_adapter(pHddCtx,
4285 WLAN_HDD_INFRA_STATION);
4286 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004287 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004288 /* DeRegister with platform driver as client for Suspend/Resume */
4289 vosStatus = hddDeregisterPmOps(pHddCtx);
4290 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4291 {
4292 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4293 VOS_ASSERT(0);
4294 }
4295
4296 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4297 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4298 {
4299 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4300 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004301
4302 // Cancel any outstanding scan requests. We are about to close all
4303 // of our adapters, but an adapter structure is what SME passes back
4304 // to our callback function. Hence if there are any outstanding scan
4305 // requests then there is a race condition between when the adapter
4306 // is closed and when the callback is invoked. We try to resolve that
4307 // race condition here by canceling any outstanding scans before we
4308 // close the adapters.
4309 // Note that the scans may be cancelled in an asynchronous manner, so
4310 // ideally there needs to be some kind of synchronization. Rather than
4311 // introduce a new synchronization here, we will utilize the fact that
4312 // we are about to Request Full Power, and since that is synchronized,
4313 // the expectation is that by the time Request Full Power has completed,
4314 // all scans will be cancelled.
4315 hdd_abort_mac_scan( pHddCtx );
4316
4317 //Disable IMPS/BMPS as we do not want the device to enter any power
4318 //save mode during shutdown
4319 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4320 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4321 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4322
4323 //Ensure that device is in full power as we will touch H/W during vos_Stop
4324 init_completion(&powerContext.completion);
4325 powerContext.magic = POWER_CONTEXT_MAGIC;
4326
4327 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4328 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4329
4330 if (eHAL_STATUS_SUCCESS != halStatus)
4331 {
4332 if (eHAL_STATUS_PMC_PENDING == halStatus)
4333 {
4334 /* request was sent -- wait for the response */
4335 lrc = wait_for_completion_interruptible_timeout(
4336 &powerContext.completion,
4337 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4338 /* either we have a response or we timed out
4339 either way, first invalidate our magic */
4340 powerContext.magic = 0;
4341 if (lrc <= 0)
4342 {
4343 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004344 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004345 /* there is a race condition such that the callback
4346 function could be executing at the same time we are. of
4347 primary concern is if the callback function had already
4348 verified the "magic" but hasn't yet set the completion
4349 variable. Since the completion variable is on our
4350 stack, we'll delay just a bit to make sure the data is
4351 still valid if that is the case */
4352 msleep(50);
4353 }
4354 }
4355 else
4356 {
4357 hddLog(VOS_TRACE_LEVEL_ERROR,
4358 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004359 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004360 VOS_ASSERT(0);
4361 /* continue -- need to clean up as much as possible */
4362 }
4363 }
4364
4365 // Unregister the Net Device Notifier
4366 unregister_netdevice_notifier(&hdd_netdev_notifier);
4367
Jeff Johnson295189b2012-06-20 16:38:30 -07004368 hdd_stop_all_adapters( pHddCtx );
4369
Jeff Johnson295189b2012-06-20 16:38:30 -07004370#ifdef WLAN_BTAMP_FEATURE
4371 vosStatus = WLANBAP_Stop(pVosContext);
4372 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4373 {
4374 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4375 "%s: Failed to stop BAP",__func__);
4376 }
4377#endif //WLAN_BTAMP_FEATURE
4378
4379 //Stop all the modules
4380 vosStatus = vos_stop( pVosContext );
4381 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4382 {
4383 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4384 "%s: Failed to stop VOSS",__func__);
4385 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4386 }
4387
Jeff Johnson295189b2012-06-20 16:38:30 -07004388 //Assert Deep sleep signal now to put Libra HW in lowest power state
4389 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4390 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4391
4392 //Vote off any PMIC voltage supplies
4393 vos_chipPowerDown(NULL, NULL, NULL);
4394
4395 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4396
4397 //Clean up HDD Nlink Service
4398 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
4399 nl_srv_exit();
4400
4401 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004402 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004403
4404 //Close the scheduler before calling vos_close to make sure no thread is
4405 // scheduled after the each module close is called i.e after all the data
4406 // structures are freed.
4407 vosStatus = vos_sched_close( pVosContext );
4408 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4409 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4410 "%s: Failed to close VOSS Scheduler",__func__);
4411 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4412 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004413#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004414#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4415 /* Destroy the wake lock */
4416 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4417#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004418 /* Destroy the wake lock */
4419 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004420#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004421
4422 //Close VOSS
4423 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4424 vos_close(pVosContext);
4425
Jeff Johnson295189b2012-06-20 16:38:30 -07004426 //Close Watchdog
4427 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4428 vos_watchdog_close(pVosContext);
4429
4430 /* Cancel the vote for XO Core ON.
4431 * This is done here to ensure there is no race condition since MC, TX and WD threads have
4432 * exited at this point
4433 */
4434 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
4435 " when WLAN is turned OFF\n");
4436 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4437 {
4438 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
4439 " Not returning failure."
4440 " Power consumed will be high\n");
4441 }
4442
4443 hdd_close_all_adapters( pHddCtx );
4444
4445
4446 //Free up dynamically allocated members inside HDD Adapter
4447 kfree(pHddCtx->cfg_ini);
4448 pHddCtx->cfg_ini= NULL;
4449
4450 /* free the power on lock from platform driver */
4451 if (free_riva_power_on_lock("wlan"))
4452 {
4453 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
4454 __func__);
4455 }
4456
Jeff Johnson88ba7742013-02-27 14:36:02 -08004457free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08004458 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004459 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004460 if (hdd_is_ssr_required())
4461 {
4462 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07004463 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07004464 msleep(5000);
4465 }
4466 hdd_set_ssr_required (VOS_FALSE);
4467}
4468
4469
4470/**---------------------------------------------------------------------------
4471
4472 \brief hdd_update_config_from_nv() - Function to update the contents of
4473 the running configuration with parameters taken from NV storage
4474
4475 \param - pHddCtx - Pointer to the HDD global context
4476
4477 \return - VOS_STATUS_SUCCESS if successful
4478
4479 --------------------------------------------------------------------------*/
4480static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
4481{
Jeff Johnson295189b2012-06-20 16:38:30 -07004482 v_BOOL_t itemIsValid = VOS_FALSE;
4483 VOS_STATUS status;
4484 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
4485 v_U8_t macLoop;
4486
4487 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
4488 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
4489 if(status != VOS_STATUS_SUCCESS)
4490 {
4491 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
4492 return VOS_STATUS_E_FAILURE;
4493 }
4494
4495 if (itemIsValid == VOS_TRUE)
4496 {
4497 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
4498 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
4499 VOS_MAX_CONCURRENCY_PERSONA);
4500 if(status != VOS_STATUS_SUCCESS)
4501 {
4502 /* Get MAC from NV fail, not update CFG info
4503 * INI MAC value will be used for MAC setting */
4504 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
4505 return VOS_STATUS_E_FAILURE;
4506 }
4507
4508 /* If first MAC is not valid, treat all others are not valid
4509 * Then all MACs will be got from ini file */
4510 if(vos_is_macaddr_zero(&macFromNV[0]))
4511 {
4512 /* MAC address in NV file is not configured yet */
4513 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
4514 return VOS_STATUS_E_INVAL;
4515 }
4516
4517 /* Get MAC address from NV, update CFG info */
4518 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
4519 {
4520 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
4521 {
4522 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
4523 /* This MAC is not valid, skip it
4524 * This MAC will be got from ini file */
4525 }
4526 else
4527 {
4528 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
4529 (v_U8_t *)&macFromNV[macLoop].bytes[0],
4530 VOS_MAC_ADDR_SIZE);
4531 }
4532 }
4533 }
4534 else
4535 {
4536 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
4537 return VOS_STATUS_E_FAILURE;
4538 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004539
Jeff Johnson295189b2012-06-20 16:38:30 -07004540
4541 return VOS_STATUS_SUCCESS;
4542}
4543
4544/**---------------------------------------------------------------------------
4545
4546 \brief hdd_post_voss_start_config() - HDD post voss start config helper
4547
4548 \param - pAdapter - Pointer to the HDD
4549
4550 \return - None
4551
4552 --------------------------------------------------------------------------*/
4553VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
4554{
4555 eHalStatus halStatus;
4556 v_U32_t listenInterval;
4557
Jeff Johnson295189b2012-06-20 16:38:30 -07004558
4559 // Send ready indication to the HDD. This will kick off the MAC
4560 // into a 'running' state and should kick off an initial scan.
4561 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
4562 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4563 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304564 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07004565 "code %08d [x%08x]",__func__, halStatus, halStatus );
4566 return VOS_STATUS_E_FAILURE;
4567 }
4568
4569 // Set default LI into HDD context,
4570 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
4571 // And RIVA will crash
4572 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
4573 pHddCtx->hdd_actual_LI_value = listenInterval;
4574
4575 return VOS_STATUS_SUCCESS;
4576}
4577
Jeff Johnson295189b2012-06-20 16:38:30 -07004578/* wake lock APIs for HDD */
4579void hdd_prevent_suspend(void)
4580{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004581#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004582 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004583#else
4584 wcnss_prevent_suspend();
4585#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004586}
4587
4588void hdd_allow_suspend(void)
4589{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004590#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004591 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004592#else
4593 wcnss_allow_suspend();
4594#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004595}
4596
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004597void hdd_allow_suspend_timeout(v_U32_t timeout)
4598{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004599#ifdef WLAN_OPEN_SOURCE
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004600 wake_lock_timeout(&wlan_wake_lock, timeout);
4601#else
4602 /* Do nothing as there is no API in wcnss for timeout*/
4603#endif
4604}
4605
Jeff Johnson295189b2012-06-20 16:38:30 -07004606/**---------------------------------------------------------------------------
4607
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004608 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
4609 information between Host and Riva
4610
4611 This function gets reported version of FW
4612 It also finds the version of Riva headers used to compile the host
4613 It compares the above two and prints a warning if they are different
4614 It gets the SW and HW version string
4615 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
4616 indicating the features they support through a bitmap
4617
4618 \param - pHddCtx - Pointer to HDD context
4619
4620 \return - void
4621
4622 --------------------------------------------------------------------------*/
4623
4624void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
4625{
4626
4627 tSirVersionType versionCompiled;
4628 tSirVersionType versionReported;
4629 tSirVersionString versionString;
4630 tANI_U8 fwFeatCapsMsgSupported = 0;
4631 VOS_STATUS vstatus;
4632
4633 /* retrieve and display WCNSS version information */
4634 do {
4635
4636 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
4637 &versionCompiled);
4638 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4639 {
4640 hddLog(VOS_TRACE_LEVEL_FATAL,
4641 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004642 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004643 break;
4644 }
4645
4646 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
4647 &versionReported);
4648 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4649 {
4650 hddLog(VOS_TRACE_LEVEL_FATAL,
4651 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004652 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004653 break;
4654 }
4655
4656 if ((versionCompiled.major != versionReported.major) ||
4657 (versionCompiled.minor != versionReported.minor) ||
4658 (versionCompiled.version != versionReported.version) ||
4659 (versionCompiled.revision != versionReported.revision))
4660 {
4661 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4662 "Host expected %u.%u.%u.%u\n",
4663 WLAN_MODULE_NAME,
4664 (int)versionReported.major,
4665 (int)versionReported.minor,
4666 (int)versionReported.version,
4667 (int)versionReported.revision,
4668 (int)versionCompiled.major,
4669 (int)versionCompiled.minor,
4670 (int)versionCompiled.version,
4671 (int)versionCompiled.revision);
4672 }
4673 else
4674 {
4675 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4676 WLAN_MODULE_NAME,
4677 (int)versionReported.major,
4678 (int)versionReported.minor,
4679 (int)versionReported.version,
4680 (int)versionReported.revision);
4681 }
4682
4683 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
4684 versionString,
4685 sizeof(versionString));
4686 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4687 {
4688 hddLog(VOS_TRACE_LEVEL_FATAL,
4689 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004690 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004691 break;
4692 }
4693
4694 pr_info("%s: WCNSS software version %s\n",
4695 WLAN_MODULE_NAME, versionString);
4696
4697 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
4698 versionString,
4699 sizeof(versionString));
4700 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4701 {
4702 hddLog(VOS_TRACE_LEVEL_FATAL,
4703 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004704 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004705 break;
4706 }
4707
4708 pr_info("%s: WCNSS hardware version %s\n",
4709 WLAN_MODULE_NAME, versionString);
4710
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004711 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
4712 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004713 send the message only if it the riva is 1.1
4714 minor numbers for different riva branches:
4715 0 -> (1.0)Mainline Build
4716 1 -> (1.1)Mainline Build
4717 2->(1.04) Stability Build
4718 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004719 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004720 ((versionReported.minor>=1) && (versionReported.version>=1)))
4721 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
4722 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004723
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004724 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08004725 {
4726#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4727 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
4728 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
4729#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004730 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08004731 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004732
4733 } while (0);
4734
4735}
4736
4737/**---------------------------------------------------------------------------
4738
Jeff Johnson295189b2012-06-20 16:38:30 -07004739 \brief hdd_wlan_startup() - HDD init function
4740
4741 This is the driver startup code executed once a WLAN device has been detected
4742
4743 \param - dev - Pointer to the underlying device
4744
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004745 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07004746
4747 --------------------------------------------------------------------------*/
4748
4749int hdd_wlan_startup(struct device *dev )
4750{
4751 VOS_STATUS status;
4752 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004753 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004754 hdd_context_t *pHddCtx = NULL;
4755 v_CONTEXT_t pVosContext= NULL;
4756#ifdef WLAN_BTAMP_FEATURE
4757 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
4758 WLANBAP_ConfigType btAmpConfig;
4759 hdd_config_t *pConfig;
4760#endif
4761 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07004762 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004763
4764 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07004765 /*
4766 * cfg80211: wiphy allocation
4767 */
4768 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
4769
4770 if(wiphy == NULL)
4771 {
4772 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004773 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004774 }
4775
4776 pHddCtx = wiphy_priv(wiphy);
4777
Jeff Johnson295189b2012-06-20 16:38:30 -07004778 //Initialize the adapter context to zeros.
4779 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
4780
Jeff Johnson295189b2012-06-20 16:38:30 -07004781 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004782 hdd_prevent_suspend();
4783 pHddCtx->isLoadUnloadInProgress = TRUE;
4784
4785 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4786
4787 /*Get vos context here bcoz vos_open requires it*/
4788 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4789
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08004790 if(pVosContext == NULL)
4791 {
4792 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
4793 goto err_free_hdd_context;
4794 }
4795
Jeff Johnson295189b2012-06-20 16:38:30 -07004796 //Save the Global VOSS context in adapter context for future.
4797 pHddCtx->pvosContext = pVosContext;
4798
4799 //Save the adapter context in global context for future.
4800 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
4801
Jeff Johnson295189b2012-06-20 16:38:30 -07004802 pHddCtx->parent_dev = dev;
4803
4804 init_completion(&pHddCtx->full_pwr_comp_var);
4805 init_completion(&pHddCtx->standby_comp_var);
4806 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004807 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004808 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004809
4810 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
4811
4812 // Load all config first as TL config is needed during vos_open
4813 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
4814 if(pHddCtx->cfg_ini == NULL)
4815 {
4816 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
4817 goto err_free_hdd_context;
4818 }
4819
4820 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
4821
4822 // Read and parse the qcom_cfg.ini file
4823 status = hdd_parse_config_ini( pHddCtx );
4824 if ( VOS_STATUS_SUCCESS != status )
4825 {
4826 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
4827 __func__, WLAN_INI_FILE);
4828 goto err_config;
4829 }
4830
Jeff Johnson295189b2012-06-20 16:38:30 -07004831 /*
4832 * cfg80211: Initialization and registration ...
4833 */
4834 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
4835 {
4836 hddLog(VOS_TRACE_LEVEL_FATAL,
4837 "%s: wlan_hdd_cfg80211_register return failure", __func__);
4838 goto err_wiphy_reg;
4839 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004840
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004841 // Update VOS trace levels based upon the cfg.ini
4842 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
4843 pHddCtx->cfg_ini->vosTraceEnableBAP);
4844 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
4845 pHddCtx->cfg_ini->vosTraceEnableTL);
4846 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
4847 pHddCtx->cfg_ini->vosTraceEnableWDI);
4848 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
4849 pHddCtx->cfg_ini->vosTraceEnableHDD);
4850 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
4851 pHddCtx->cfg_ini->vosTraceEnableSME);
4852 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
4853 pHddCtx->cfg_ini->vosTraceEnablePE);
4854 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
4855 pHddCtx->cfg_ini->vosTraceEnableWDA);
4856 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
4857 pHddCtx->cfg_ini->vosTraceEnableSYS);
4858 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
4859 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004860 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
4861 pHddCtx->cfg_ini->vosTraceEnableSAP);
4862 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
4863 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004864
Jeff Johnson295189b2012-06-20 16:38:30 -07004865 // Update WDI trace levels based upon the cfg.ini
4866 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
4867 pHddCtx->cfg_ini->wdiTraceEnableDAL);
4868 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
4869 pHddCtx->cfg_ini->wdiTraceEnableCTL);
4870 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
4871 pHddCtx->cfg_ini->wdiTraceEnableDAT);
4872 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
4873 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004874
Jeff Johnson88ba7742013-02-27 14:36:02 -08004875 if (VOS_FTM_MODE == hdd_get_conparam())
4876 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004877 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
4878 {
4879 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
4880 goto err_free_hdd_context;
4881 }
4882 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
4883 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08004884 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004885
Jeff Johnson88ba7742013-02-27 14:36:02 -08004886 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07004887 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4888 {
4889 status = vos_watchdog_open(pVosContext,
4890 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
4891
4892 if(!VOS_IS_STATUS_SUCCESS( status ))
4893 {
4894 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004895 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07004896 }
4897 }
4898
4899 pHddCtx->isLogpInProgress = FALSE;
4900 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4901
Jeff Johnson295189b2012-06-20 16:38:30 -07004902 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
4903 if(!VOS_IS_STATUS_SUCCESS(status))
4904 {
4905 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004906 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004907 }
4908
Jeff Johnson295189b2012-06-20 16:38:30 -07004909 status = vos_open( &pVosContext, 0);
4910 if ( !VOS_IS_STATUS_SUCCESS( status ))
4911 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004912 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
4913 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07004914 }
4915
Jeff Johnson295189b2012-06-20 16:38:30 -07004916 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
4917
4918 if ( NULL == pHddCtx->hHal )
4919 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004920 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004921 goto err_vosclose;
4922 }
4923
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004924 status = vos_preStart( pHddCtx->pvosContext );
4925 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4926 {
4927 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
4928 goto err_vosclose;
4929 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004930
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004931 /* Note that the vos_preStart() sequence triggers the cfg download.
4932 The cfg download must occur before we update the SME config
4933 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07004934 status = hdd_set_sme_config( pHddCtx );
4935
4936 if ( VOS_STATUS_SUCCESS != status )
4937 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004938 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
4939 goto err_vosclose;
4940 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004941
4942 //Initialize the WMM module
4943 status = hdd_wmm_init(pHddCtx);
4944 if (!VOS_IS_STATUS_SUCCESS(status))
4945 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004946 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004947 goto err_vosclose;
4948 }
4949
Jeff Johnson295189b2012-06-20 16:38:30 -07004950 /* In the integrated architecture we update the configuration from
4951 the INI file and from NV before vOSS has been started so that
4952 the final contents are available to send down to the cCPU */
4953
4954 // Apply the cfg.ini to cfg.dat
4955 if (FALSE == hdd_update_config_dat(pHddCtx))
4956 {
4957 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
4958 goto err_vosclose;
4959 }
4960
4961 // Apply the NV to cfg.dat
4962 /* Prima Update MAC address only at here */
4963 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
4964 {
4965#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
4966 /* There was not a valid set of MAC Addresses in NV. See if the
4967 default addresses were modified by the cfg.ini settings. If so,
4968 we'll use them, but if not, we'll autogenerate a set of MAC
4969 addresses based upon the device serial number */
4970
4971 static const v_MACADDR_t default_address =
4972 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
4973 unsigned int serialno;
4974 int i;
4975
4976 serialno = wcnss_get_serial_number();
4977 if ((0 != serialno) &&
4978 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
4979 sizeof(default_address))))
4980 {
4981 /* cfg.ini has the default address, invoke autogen logic */
4982
4983 /* MAC address has 3 bytes of OUI so we have a maximum of 3
4984 bytes of the serial number that can be used to generate
4985 the other 3 bytes of the MAC address. Mask off all but
4986 the lower 3 bytes (this will also make sure we don't
4987 overflow in the next step) */
4988 serialno &= 0x00FFFFFF;
4989
4990 /* we need a unique address for each session */
4991 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
4992
4993 /* autogen all addresses */
4994 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4995 {
4996 /* start with the entire default address */
4997 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
4998 /* then replace the lower 3 bytes */
4999 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5000 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5001 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5002
5003 serialno++;
5004 }
5005
5006 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5007 MAC_ADDRESS_STR,
5008 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5009 }
5010 else
5011#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5012 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005013 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005014 "%s: Invalid MAC address in NV, using MAC from ini file "
5015 MAC_ADDRESS_STR, __func__,
5016 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5017 }
5018 }
5019 {
5020 eHalStatus halStatus;
5021 // Set the MAC Address
5022 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5023 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5024 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5025 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5026
5027 if (!HAL_STATUS_SUCCESS( halStatus ))
5028 {
5029 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5030 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005031 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005032 }
5033 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005034
5035 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5036 Note: Firmware image will be read and downloaded inside vos_start API */
5037 status = vos_start( pHddCtx->pvosContext );
5038 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5039 {
5040 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5041 goto err_vosclose;
5042 }
5043
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005044 /* Exchange capability info between Host and FW and also get versioning info from FW */
5045 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005046
5047 status = hdd_post_voss_start_config( pHddCtx );
5048 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5049 {
5050 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5051 __func__);
5052 goto err_vosstop;
5053 }
5054
Jeff Johnson295189b2012-06-20 16:38:30 -07005055 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5056 {
5057 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5058 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5059 }
5060 else
5061 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005062 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5063 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5064 if (pAdapter != NULL)
5065 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305066 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005067 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305068 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5069 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5070 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005071
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305072 /* Generate the P2P Device Address. This consists of the device's
5073 * primary MAC address with the locally administered bit set.
5074 */
5075 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005076 }
5077 else
5078 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305079 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5080 if (p2p_dev_addr != NULL)
5081 {
5082 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5083 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5084 }
5085 else
5086 {
5087 hddLog(VOS_TRACE_LEVEL_FATAL,
5088 "%s: Failed to allocate mac_address for p2p_device",
5089 __func__);
5090 goto err_close_adapter;
5091 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005092 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005093
5094 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5095 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5096 if ( NULL == pP2pAdapter )
5097 {
5098 hddLog(VOS_TRACE_LEVEL_FATAL,
5099 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005100 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005101 goto err_close_adapter;
5102 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005103 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005104 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005105
5106 if( pAdapter == NULL )
5107 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005108 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5109 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005110 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005111
Jeff Johnson295189b2012-06-20 16:38:30 -07005112#ifdef WLAN_BTAMP_FEATURE
5113 vStatus = WLANBAP_Open(pVosContext);
5114 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5115 {
5116 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5117 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005118 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005119 }
5120
5121 vStatus = BSL_Init(pVosContext);
5122 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5123 {
5124 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5125 "%s: Failed to Init BSL",__func__);
5126 goto err_bap_close;
5127 }
5128 vStatus = WLANBAP_Start(pVosContext);
5129 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5130 {
5131 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5132 "%s: Failed to start TL",__func__);
5133 goto err_bap_close;
5134 }
5135
5136 pConfig = pHddCtx->cfg_ini;
5137 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5138 status = WLANBAP_SetConfig(&btAmpConfig);
5139
5140#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005141
Jeff Johnson295189b2012-06-20 16:38:30 -07005142#ifdef FEATURE_WLAN_SCAN_PNO
5143 /*SME must send channel update configuration to RIVA*/
5144 sme_UpdateChannelConfig(pHddCtx->hHal);
5145#endif
5146
Jeff Johnson295189b2012-06-20 16:38:30 -07005147 /* Register with platform driver as client for Suspend/Resume */
5148 status = hddRegisterPmOps(pHddCtx);
5149 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5150 {
5151 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5152#ifdef WLAN_BTAMP_FEATURE
5153 goto err_bap_stop;
5154#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005155 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005156#endif //WLAN_BTAMP_FEATURE
5157 }
5158
5159 /* Register TM level change handler function to the platform */
5160 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5161 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5162 {
5163 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5164 goto err_unregister_pmops;
5165 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005166
5167 /* register for riva power on lock to platform driver */
5168 if (req_riva_power_on_lock("wlan"))
5169 {
5170 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5171 __func__);
5172 goto err_unregister_pmops;
5173 }
5174
Jeff Johnson295189b2012-06-20 16:38:30 -07005175 // register net device notifier for device change notification
5176 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5177
5178 if(ret < 0)
5179 {
5180 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5181 goto err_free_power_on_lock;
5182 }
5183
5184 //Initialize the nlink service
5185 if(nl_srv_init() != 0)
5186 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305187 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005188 goto err_reg_netdev;
5189 }
5190
5191 //Initialize the BTC service
5192 if(btc_activate_service(pHddCtx) != 0)
5193 {
5194 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5195 goto err_nl_srv;
5196 }
5197
5198#ifdef PTT_SOCK_SVC_ENABLE
5199 //Initialize the PTT service
5200 if(ptt_sock_activate_svc(pHddCtx) != 0)
5201 {
5202 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5203 goto err_nl_srv;
5204 }
5205#endif
5206
Jeff Johnson295189b2012-06-20 16:38:30 -07005207 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005208 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005209 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005210 /* Action frame registered in one adapter which will
5211 * applicable to all interfaces
5212 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005213 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005214 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005215
5216 mutex_init(&pHddCtx->sap_lock);
5217
5218 pHddCtx->isLoadUnloadInProgress = FALSE;
5219
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005220#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005221#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5222 /* Initialize the wake lcok */
5223 wake_lock_init(&pHddCtx->rx_wake_lock,
5224 WAKE_LOCK_SUSPEND,
5225 "qcom_rx_wakelock");
5226#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005227 /* Initialize the wake lcok */
5228 wake_lock_init(&pHddCtx->sap_wake_lock,
5229 WAKE_LOCK_SUSPEND,
5230 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005231#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005232
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005233 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5234 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005235
5236 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5237 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005238
5239 // Initialize the restart logic
5240 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305241
Jeff Johnson295189b2012-06-20 16:38:30 -07005242 goto success;
5243
5244err_nl_srv:
5245 nl_srv_exit();
5246
5247err_reg_netdev:
5248 unregister_netdevice_notifier(&hdd_netdev_notifier);
5249
5250err_free_power_on_lock:
5251 free_riva_power_on_lock("wlan");
5252
5253err_unregister_pmops:
5254 hddDevTmUnregisterNotifyCallback(pHddCtx);
5255 hddDeregisterPmOps(pHddCtx);
5256
5257#ifdef WLAN_BTAMP_FEATURE
5258err_bap_stop:
5259 WLANBAP_Stop(pVosContext);
5260#endif
5261
5262#ifdef WLAN_BTAMP_FEATURE
5263err_bap_close:
5264 WLANBAP_Close(pVosContext);
5265#endif
5266
Jeff Johnson295189b2012-06-20 16:38:30 -07005267err_close_adapter:
5268 hdd_close_all_adapters( pHddCtx );
5269
5270err_vosstop:
5271 vos_stop(pVosContext);
5272
5273err_vosclose:
5274 status = vos_sched_close( pVosContext );
5275 if (!VOS_IS_STATUS_SUCCESS(status)) {
5276 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5277 "%s: Failed to close VOSS Scheduler", __func__);
5278 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5279 }
5280 vos_close(pVosContext );
5281
Jeff Johnson295189b2012-06-20 16:38:30 -07005282err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005283 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005284
5285err_wdclose:
5286 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5287 vos_watchdog_close(pVosContext);
5288
Jeff Johnson295189b2012-06-20 16:38:30 -07005289err_wiphy_reg:
5290 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005291
5292err_config:
5293 kfree(pHddCtx->cfg_ini);
5294 pHddCtx->cfg_ini= NULL;
5295
5296err_free_hdd_context:
5297 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005298 wiphy_free(wiphy) ;
5299 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005300 VOS_BUG(1);
5301
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005302 if (hdd_is_ssr_required())
5303 {
5304 /* WDI timeout had happened during load, so SSR is needed here */
5305 subsystem_restart("wcnss");
5306 msleep(5000);
5307 }
5308 hdd_set_ssr_required (VOS_FALSE);
5309
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005310 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005311
5312success:
5313 EXIT();
5314 return 0;
5315}
5316
5317/**---------------------------------------------------------------------------
5318
Jeff Johnson32d95a32012-09-10 13:15:23 -07005319 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07005320
Jeff Johnson32d95a32012-09-10 13:15:23 -07005321 This is the driver entry point - called in different timeline depending
5322 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07005323
5324 \param - None
5325
5326 \return - 0 for success, non zero for failure
5327
5328 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07005329static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005330{
5331 VOS_STATUS status;
5332 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005333 struct device *dev = NULL;
5334 int ret_status = 0;
5335
5336 ENTER();
5337
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005338#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005339 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07005340#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005341
5342 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
5343 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
5344
5345 //Power Up Libra WLAN card first if not already powered up
5346 status = vos_chipPowerUp(NULL,NULL,NULL);
5347 if (!VOS_IS_STATUS_SUCCESS(status))
5348 {
5349 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
5350 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005351 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005352 }
5353
Jeff Johnson295189b2012-06-20 16:38:30 -07005354#ifdef ANI_BUS_TYPE_PCI
5355
5356 dev = wcnss_wlan_get_device();
5357
5358#endif // ANI_BUS_TYPE_PCI
5359
5360#ifdef ANI_BUS_TYPE_PLATFORM
5361 dev = wcnss_wlan_get_device();
5362#endif // ANI_BUS_TYPE_PLATFORM
5363
5364
5365 do {
5366 if (NULL == dev) {
5367 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
5368 ret_status = -1;
5369 break;
5370 }
5371
5372#ifdef MEMORY_DEBUG
5373 vos_mem_init();
5374#endif
5375
5376#ifdef TIMER_MANAGER
5377 vos_timer_manager_init();
5378#endif
5379
5380 /* Preopen VOSS so that it is ready to start at least SAL */
5381 status = vos_preOpen(&pVosContext);
5382
5383 if (!VOS_IS_STATUS_SUCCESS(status))
5384 {
5385 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
5386 ret_status = -1;
5387 break;
5388 }
5389
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005390#ifndef MODULE
5391 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
5392 */
5393 hdd_set_conparam((v_UINT_t)con_mode);
5394#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005395
5396 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005397 if (hdd_wlan_startup(dev))
5398 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005399 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005400 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005401 vos_preClose( &pVosContext );
5402 ret_status = -1;
5403 break;
5404 }
5405
5406 /* Cancel the vote for XO Core ON
5407 * This is done here for safety purposes in case we re-initialize without turning
5408 * it OFF in any error scenario.
5409 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005410 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07005411 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005412 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07005413 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5414 {
5415 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
5416 " Power consumed will be high\n");
5417 }
5418 } while (0);
5419
5420 if (0 != ret_status)
5421 {
5422 //Assert Deep sleep signal now to put Libra HW in lowest power state
5423 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5424 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
5425
5426 //Vote off any PMIC voltage supplies
5427 vos_chipPowerDown(NULL, NULL, NULL);
5428#ifdef TIMER_MANAGER
5429 vos_timer_exit();
5430#endif
5431#ifdef MEMORY_DEBUG
5432 vos_mem_exit();
5433#endif
5434
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005435#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005436 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005437#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005438 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
5439 }
5440 else
5441 {
5442 //Send WLAN UP indication to Nlink Service
5443 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
5444
5445 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
5446
5447 }
5448
5449 EXIT();
5450
5451 return ret_status;
5452}
5453
Jeff Johnson32d95a32012-09-10 13:15:23 -07005454/**---------------------------------------------------------------------------
5455
5456 \brief hdd_module_init() - Init Function
5457
5458 This is the driver entry point (invoked when module is loaded using insmod)
5459
5460 \param - None
5461
5462 \return - 0 for success, non zero for failure
5463
5464 --------------------------------------------------------------------------*/
5465#ifdef MODULE
5466static int __init hdd_module_init ( void)
5467{
5468 return hdd_driver_init();
5469}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005470#else /* #ifdef MODULE */
5471static int __init hdd_module_init ( void)
5472{
5473 /* Driver initialization is delayed to fwpath_changed_handler */
5474 return 0;
5475}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005476#endif /* #ifdef MODULE */
5477
Jeff Johnson295189b2012-06-20 16:38:30 -07005478
5479/**---------------------------------------------------------------------------
5480
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005481 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005482
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005483 This is the driver exit point (invoked when module is unloaded using rmmod
5484 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07005485
5486 \param - None
5487
5488 \return - None
5489
5490 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005491static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005492{
5493 hdd_context_t *pHddCtx = NULL;
5494 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005495
5496 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
5497
5498 //Get the global vos context
5499 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5500
5501 if(!pVosContext)
5502 {
5503 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
5504 goto done;
5505 }
5506
5507 //Get the HDD context.
5508 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
5509
5510 if(!pHddCtx)
5511 {
5512 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
5513 }
5514 else
5515 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005516 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07005517 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07005518 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
5519 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07005520 }
5521
5522 pHddCtx->isLoadUnloadInProgress = TRUE;
5523 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5524
5525 //Do all the cleanup before deregistering the driver
5526 hdd_wlan_exit(pHddCtx);
5527 }
5528
Jeff Johnson295189b2012-06-20 16:38:30 -07005529 vos_preClose( &pVosContext );
5530
5531#ifdef TIMER_MANAGER
5532 vos_timer_exit();
5533#endif
5534#ifdef MEMORY_DEBUG
5535 vos_mem_exit();
5536#endif
5537
5538done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005539#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005540 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005541#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005542 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
5543}
5544
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005545/**---------------------------------------------------------------------------
5546
5547 \brief hdd_module_exit() - Exit function
5548
5549 This is the driver exit point (invoked when module is unloaded using rmmod)
5550
5551 \param - None
5552
5553 \return - None
5554
5555 --------------------------------------------------------------------------*/
5556static void __exit hdd_module_exit(void)
5557{
5558 hdd_driver_exit();
5559}
5560
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005561#ifdef MODULE
5562static int fwpath_changed_handler(const char *kmessage,
5563 struct kernel_param *kp)
5564{
Jeff Johnson76052702013-04-16 13:55:05 -07005565 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005566}
5567
5568static int con_mode_handler(const char *kmessage,
5569 struct kernel_param *kp)
5570{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07005571 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005572}
5573#else /* #ifdef MODULE */
5574/**---------------------------------------------------------------------------
5575
Jeff Johnson76052702013-04-16 13:55:05 -07005576 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005577
Jeff Johnson76052702013-04-16 13:55:05 -07005578 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005579 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07005580 - invoked when module parameter fwpath is modified from userspace to signal
5581 initializing the WLAN driver or when con_mode is modified from userspace
5582 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005583
5584 \return - 0 for success, non zero for failure
5585
5586 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07005587static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005588{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005589 int ret_status;
5590
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005591 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005592 ret_status = hdd_driver_init();
5593 wlan_hdd_inited = ret_status ? 0 : 1;
5594 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005595 }
5596
5597 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07005598
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005599 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07005600
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005601 ret_status = hdd_driver_init();
5602 wlan_hdd_inited = ret_status ? 0 : 1;
5603 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005604}
5605
Jeff Johnson295189b2012-06-20 16:38:30 -07005606/**---------------------------------------------------------------------------
5607
Jeff Johnson76052702013-04-16 13:55:05 -07005608 \brief fwpath_changed_handler() - Handler Function
5609
5610 Handle changes to the fwpath parameter
5611
5612 \return - 0 for success, non zero for failure
5613
5614 --------------------------------------------------------------------------*/
5615static int fwpath_changed_handler(const char *kmessage,
5616 struct kernel_param *kp)
5617{
5618 int ret;
5619
5620 ret = param_set_copystring(kmessage, kp);
5621 if (0 == ret)
5622 ret = kickstart_driver();
5623 return ret;
5624}
5625
5626/**---------------------------------------------------------------------------
5627
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005628 \brief con_mode_handler() -
5629
5630 Handler function for module param con_mode when it is changed by userspace
5631 Dynamically linked - do nothing
5632 Statically linked - exit and init driver, as in rmmod and insmod
5633
Jeff Johnson76052702013-04-16 13:55:05 -07005634 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005635
Jeff Johnson76052702013-04-16 13:55:05 -07005636 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005637
5638 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07005639static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005640{
Jeff Johnson76052702013-04-16 13:55:05 -07005641 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005642
Jeff Johnson76052702013-04-16 13:55:05 -07005643 ret = param_set_int(kmessage, kp);
5644 if (0 == ret)
5645 ret = kickstart_driver();
5646 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005647}
5648#endif /* #ifdef MODULE */
5649
5650/**---------------------------------------------------------------------------
5651
Jeff Johnson295189b2012-06-20 16:38:30 -07005652 \brief hdd_get_conparam() -
5653
5654 This is the driver exit point (invoked when module is unloaded using rmmod)
5655
5656 \param - None
5657
5658 \return - tVOS_CON_MODE
5659
5660 --------------------------------------------------------------------------*/
5661tVOS_CON_MODE hdd_get_conparam ( void )
5662{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005663#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07005664 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005665#else
5666 return (tVOS_CON_MODE)curr_con_mode;
5667#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005668}
5669void hdd_set_conparam ( v_UINT_t newParam )
5670{
5671 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005672#ifndef MODULE
5673 curr_con_mode = con_mode;
5674#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005675}
5676/**---------------------------------------------------------------------------
5677
5678 \brief hdd_softap_sta_deauth() - function
5679
5680 This to take counter measure to handle deauth req from HDD
5681
5682 \param - pAdapter - Pointer to the HDD
5683
5684 \param - enable - boolean value
5685
5686 \return - None
5687
5688 --------------------------------------------------------------------------*/
5689
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005690VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07005691{
Jeff Johnson295189b2012-06-20 16:38:30 -07005692 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005693 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07005694
5695 ENTER();
5696
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305697 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07005698
5699 //Ignore request to deauth bcmc station
5700 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005701 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005702
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005703 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07005704
5705 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005706 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005707}
5708
5709/**---------------------------------------------------------------------------
5710
5711 \brief hdd_softap_sta_disassoc() - function
5712
5713 This to take counter measure to handle deauth req from HDD
5714
5715 \param - pAdapter - Pointer to the HDD
5716
5717 \param - enable - boolean value
5718
5719 \return - None
5720
5721 --------------------------------------------------------------------------*/
5722
5723void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
5724{
5725 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5726
5727 ENTER();
5728
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305729 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07005730
5731 //Ignore request to disassoc bcmc station
5732 if( pDestMacAddress[0] & 0x1 )
5733 return;
5734
5735 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
5736}
5737
5738void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
5739{
5740 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5741
5742 ENTER();
5743
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305744 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07005745
5746 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
5747}
5748
Jeff Johnson295189b2012-06-20 16:38:30 -07005749/**---------------------------------------------------------------------------
5750 *
5751 * \brief hdd_get__concurrency_mode() -
5752 *
5753 *
5754 * \param - None
5755 *
5756 * \return - CONCURRENCY MODE
5757 *
5758 * --------------------------------------------------------------------------*/
5759tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
5760{
5761 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5762 hdd_context_t *pHddCtx;
5763
5764 if (NULL != pVosContext)
5765 {
5766 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5767 if (NULL != pHddCtx)
5768 {
5769 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
5770 }
5771 }
5772
5773 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005774 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005775 return VOS_STA;
5776}
5777
5778/* Decide whether to allow/not the apps power collapse.
5779 * Allow apps power collapse if we are in connected state.
5780 * if not, allow only if we are in IMPS */
5781v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
5782{
5783 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08005784 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005785 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07005786 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5787 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5788 hdd_adapter_t *pAdapter = NULL;
5789 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08005790 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005791
Jeff Johnson295189b2012-06-20 16:38:30 -07005792 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5793 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005794
Yathish9f22e662012-12-10 14:21:35 -08005795 concurrent_state = hdd_get_concurrency_mode();
5796
5797#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5798 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
5799 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
5800 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
5801 return TRUE;
5802#endif
5803
Jeff Johnson295189b2012-06-20 16:38:30 -07005804 /*loop through all adapters. TBD fix for Concurrency */
5805 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5806 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5807 {
5808 pAdapter = pAdapterNode->pAdapter;
5809 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
5810 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5811 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005812 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07005813 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08005814 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005815 (eANI_BOOLEAN_TRUE == scanRspPending) ||
5816 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07005817 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005818 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005819 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
5820 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07005821 return FALSE;
5822 }
5823 }
5824 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5825 pAdapterNode = pNext;
5826 }
5827 return TRUE;
5828}
5829
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08005830/* Decides whether to send suspend notification to Riva
5831 * if any adapter is in BMPS; then it is required */
5832v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
5833{
5834 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
5835 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5836
5837 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
5838 {
5839 return TRUE;
5840 }
5841 return FALSE;
5842}
5843
Jeff Johnson295189b2012-06-20 16:38:30 -07005844void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5845{
5846 switch(mode)
5847 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005848 case VOS_STA_MODE:
5849 case VOS_P2P_CLIENT_MODE:
5850 case VOS_P2P_GO_MODE:
5851 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07005852 pHddCtx->concurrency_mode |= (1 << mode);
5853 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07005854 break;
5855 default:
5856 break;
5857
5858 }
5859 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5860 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5861}
5862
5863
5864void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5865{
5866 switch(mode)
5867 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005868 case VOS_STA_MODE:
5869 case VOS_P2P_CLIENT_MODE:
5870 case VOS_P2P_GO_MODE:
5871 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005872 pHddCtx->no_of_sessions[mode]--;
5873 if (!(pHddCtx->no_of_sessions[mode]))
5874 pHddCtx->concurrency_mode &= (~(1 << mode));
5875 break;
5876 default:
5877 break;
5878 }
5879 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5880 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5881}
5882
Jeff Johnsone7245742012-09-05 17:12:55 -07005883/**---------------------------------------------------------------------------
5884 *
5885 * \brief wlan_hdd_restart_init
5886 *
5887 * This function initalizes restart timer/flag. An internal function.
5888 *
5889 * \param - pHddCtx
5890 *
5891 * \return - None
5892 *
5893 * --------------------------------------------------------------------------*/
5894
5895static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
5896{
5897 /* Initialize */
5898 pHddCtx->hdd_restart_retries = 0;
5899 atomic_set(&pHddCtx->isRestartInProgress, 0);
5900 vos_timer_init(&pHddCtx->hdd_restart_timer,
5901 VOS_TIMER_TYPE_SW,
5902 wlan_hdd_restart_timer_cb,
5903 pHddCtx);
5904}
5905/**---------------------------------------------------------------------------
5906 *
5907 * \brief wlan_hdd_restart_deinit
5908 *
5909 * This function cleans up the resources used. An internal function.
5910 *
5911 * \param - pHddCtx
5912 *
5913 * \return - None
5914 *
5915 * --------------------------------------------------------------------------*/
5916
5917static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
5918{
5919
5920 VOS_STATUS vos_status;
5921 /* Block any further calls */
5922 atomic_set(&pHddCtx->isRestartInProgress, 1);
5923 /* Cleanup */
5924 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
5925 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005926 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005927 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
5928 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005929 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005930
5931}
5932
5933/**---------------------------------------------------------------------------
5934 *
5935 * \brief wlan_hdd_framework_restart
5936 *
5937 * This function uses a cfg80211 API to start a framework initiated WLAN
5938 * driver module unload/load.
5939 *
5940 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
5941 *
5942 *
5943 * \param - pHddCtx
5944 *
5945 * \return - VOS_STATUS_SUCCESS: Success
5946 * VOS_STATUS_E_EMPTY: Adapter is Empty
5947 * VOS_STATUS_E_NOMEM: No memory
5948
5949 * --------------------------------------------------------------------------*/
5950
5951static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
5952{
5953 VOS_STATUS status = VOS_STATUS_SUCCESS;
5954 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5955 int len = (sizeof (struct ieee80211_mgmt));
5956 struct ieee80211_mgmt *mgmt = NULL;
5957
5958 /* Prepare the DEAUTH managment frame with reason code */
5959 mgmt = kzalloc(len, GFP_KERNEL);
5960 if(mgmt == NULL)
5961 {
5962 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1250df42012-12-10 14:31:52 -08005963 "%s: memory allocation failed (%d bytes)", __func__, len);
Jeff Johnsone7245742012-09-05 17:12:55 -07005964 return VOS_STATUS_E_NOMEM;
5965 }
5966 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
5967
5968 /* Iterate over all adapters/devices */
5969 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5970 do
5971 {
5972 if( (status == VOS_STATUS_SUCCESS) &&
5973 pAdapterNode &&
5974 pAdapterNode->pAdapter)
5975 {
5976 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5977 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
5978 pAdapterNode->pAdapter->dev->name,
5979 pAdapterNode->pAdapter->device_mode,
5980 pHddCtx->hdd_restart_retries + 1);
5981 /*
5982 * CFG80211 event to restart the driver
5983 *
5984 * 'cfg80211_send_unprot_deauth' sends a
5985 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
5986 * of SME(Linux Kernel) state machine.
5987 *
5988 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
5989 * the driver.
5990 *
5991 */
5992
5993 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
5994 }
5995 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5996 pAdapterNode = pNext;
5997 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
5998
5999
6000 /* Free the allocated management frame */
6001 kfree(mgmt);
6002
6003 /* Retry until we unload or reach max count */
6004 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6005 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6006
6007 return status;
6008
6009}
6010/**---------------------------------------------------------------------------
6011 *
6012 * \brief wlan_hdd_restart_timer_cb
6013 *
6014 * Restart timer callback. An internal function.
6015 *
6016 * \param - User data:
6017 *
6018 * \return - None
6019 *
6020 * --------------------------------------------------------------------------*/
6021
6022void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6023{
6024 hdd_context_t *pHddCtx = usrDataForCallback;
6025 wlan_hdd_framework_restart(pHddCtx);
6026 return;
6027
6028}
6029
6030
6031/**---------------------------------------------------------------------------
6032 *
6033 * \brief wlan_hdd_restart_driver
6034 *
6035 * This function sends an event to supplicant to restart the WLAN driver.
6036 *
6037 * This function is called from vos_wlanRestart.
6038 *
6039 * \param - pHddCtx
6040 *
6041 * \return - VOS_STATUS_SUCCESS: Success
6042 * VOS_STATUS_E_EMPTY: Adapter is Empty
6043 * VOS_STATUS_E_ALREADY: Request already in progress
6044
6045 * --------------------------------------------------------------------------*/
6046VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6047{
6048 VOS_STATUS status = VOS_STATUS_SUCCESS;
6049
6050 /* A tight check to make sure reentrancy */
6051 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6052 {
6053 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6054 "%s: WLAN restart is already in progress", __func__);
6055
6056 return VOS_STATUS_E_ALREADY;
6057 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006058 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006059#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006060 wcnss_reset_intr();
6061#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006062
Jeff Johnsone7245742012-09-05 17:12:55 -07006063 return status;
6064}
6065
6066
Jeff Johnson295189b2012-06-20 16:38:30 -07006067//Register the module init/exit functions
6068module_init(hdd_module_init);
6069module_exit(hdd_module_exit);
6070
6071MODULE_LICENSE("Dual BSD/GPL");
6072MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6073MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6074
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006075module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6076 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006077
Jeff Johnson76052702013-04-16 13:55:05 -07006078module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006079 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);