blob: 857006574a025d31195eaafa993965dc02fbfd31 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/*========================================================================
43
44 \file wlan_hdd_main.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
54/**=========================================================================
55
56 EDIT HISTORY FOR FILE
57
58
59 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
61
62
63 $Header:$ $DateTime: $ $Author: $
64
65
66 when who what, where, why
67 -------- --- --------------------------------------------------------
68 04/5/09 Shailender Created module.
69 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
70 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
71 ==========================================================================*/
72
73/*--------------------------------------------------------------------------
74 Include Files
75 ------------------------------------------------------------------------*/
76//#include <wlan_qct_driver.h>
77#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070078#include <vos_api.h>
79#include <vos_sched.h>
80#include <vos_power.h>
81#include <linux/etherdevice.h>
82#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070083#ifdef ANI_BUS_TYPE_PLATFORM
84#include <linux/wcnss_wlan.h>
85#endif //ANI_BUS_TYPE_PLATFORM
86#ifdef ANI_BUS_TYPE_PCI
87#include "wcnss_wlan.h"
88#endif /* ANI_BUS_TYPE_PCI */
89#include <wlan_hdd_tx_rx.h>
90#include <palTimer.h>
91#include <wniApi.h>
92#include <wlan_nlink_srv.h>
93#include <wlan_btc_svc.h>
94#include <wlan_hdd_cfg.h>
95#include <wlan_ptt_sock_svc.h>
96#include <wlan_hdd_wowl.h>
97#include <wlan_hdd_misc.h>
98#include <wlan_hdd_wext.h>
99#ifdef WLAN_BTAMP_FEATURE
100#include <bap_hdd_main.h>
101#include <bapInternal.h>
102#endif // WLAN_BTAMP_FEATURE
103
Jeff Johnson295189b2012-06-20 16:38:30 -0700104#include <linux/wireless.h>
105#include <net/cfg80211.h>
106#include "wlan_hdd_cfg80211.h"
107#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700108#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700109int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include "sapApi.h"
111#include <linux/semaphore.h>
112#include <mach/subsystem_restart.h>
113#include <wlan_hdd_hostapd.h>
114#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700115#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700116#include "wlan_hdd_dev_pwr.h"
117#ifdef WLAN_BTAMP_FEATURE
118#include "bap_hdd_misc.h"
119#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700120#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700121#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800122#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530123#ifdef FEATURE_WLAN_TDLS
124#include "wlan_hdd_tdls.h"
125#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700126
127#ifdef MODULE
128#define WLAN_MODULE_NAME module_name(THIS_MODULE)
129#else
130#define WLAN_MODULE_NAME "wlan"
131#endif
132
133#ifdef TIMER_MANAGER
134#define TIMER_MANAGER_STR " +TIMER_MANAGER"
135#else
136#define TIMER_MANAGER_STR ""
137#endif
138
139#ifdef MEMORY_DEBUG
140#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
141#else
142#define MEMORY_DEBUG_STR ""
143#endif
144
145/* the Android framework expects this param even though we don't use it */
146#define BUF_LEN 20
147static char fwpath[BUF_LEN];
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700148#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700149static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700150#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700151
Jeff Johnsone7245742012-09-05 17:12:55 -0700152/*
153 * The rate at which the driver sends RESTART event to supplicant
154 * once the function 'vos_wlanRestart()' is called
155 *
156 */
157#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
158#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800159#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700160static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700161#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700162/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700163static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700164
165//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700166static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
167static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
168static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
169void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800170void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700171
Jeff Johnson295189b2012-06-20 16:38:30 -0700172v_U16_t hdd_select_queue(struct net_device *dev,
173 struct sk_buff *skb);
174
175#ifdef WLAN_FEATURE_PACKET_FILTERING
176static void hdd_set_multicast_list(struct net_device *dev);
177#endif
178
179void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700180int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700181
182extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800183#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
184void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
185static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
186static VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700187static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
188 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
189 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800190#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700191static int hdd_netdev_notifier_call(struct notifier_block * nb,
192 unsigned long state,
193 void *ndev)
194{
195 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700196 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700197 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700198#ifdef WLAN_BTAMP_FEATURE
199 VOS_STATUS status;
200 hdd_context_t *pHddCtx;
201#endif
202
203 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700204 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700205 (strncmp(dev->name, "p2p", 3)))
206 return NOTIFY_DONE;
207
208 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700209 return NOTIFY_DONE;
210
Jeff Johnson295189b2012-06-20 16:38:30 -0700211 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700212 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700213
Jeff Johnson27cee452013-03-27 11:10:24 -0700214 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700215 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800216 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700217 VOS_ASSERT(0);
218 return NOTIFY_DONE;
219 }
220
Jeff Johnson27cee452013-03-27 11:10:24 -0700221 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
222 if (NULL == pHddCtx)
223 {
224 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
225 VOS_ASSERT(0);
226 return NOTIFY_DONE;
227 }
228
229 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
230 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700231
232 switch (state) {
233 case NETDEV_REGISTER:
234 break;
235
236 case NETDEV_UNREGISTER:
237 break;
238
239 case NETDEV_UP:
240 break;
241
242 case NETDEV_DOWN:
243 break;
244
245 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700246 if(TRUE == pAdapter->isLinkUpSvcNeeded)
247 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700248 break;
249
250 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700251 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700252 {
253 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800254 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700255 hdd_abort_mac_scan(pAdapter->pHddCtx);
256 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800257 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700258 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
259 if(!result)
260 {
261 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800262 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700263 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700264 }
265 }
266 else
267 {
268 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700269 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700270 }
271#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700272 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700273 status = WLANBAP_StopAmp();
274 if(VOS_STATUS_SUCCESS != status )
275 {
276 pHddCtx->isAmpAllowed = VOS_TRUE;
277 hddLog(VOS_TRACE_LEVEL_FATAL,
278 "%s: Failed to stop AMP", __func__);
279 }
280 else
281 {
282 //a state m/c implementation in PAL is TBD to avoid this delay
283 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700284 if ( pHddCtx->isAmpAllowed )
285 {
286 WLANBAP_DeregisterFromHCI();
287 pHddCtx->isAmpAllowed = VOS_FALSE;
288 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700289 }
290#endif //WLAN_BTAMP_FEATURE
291 break;
292
293 default:
294 break;
295 }
296
297 return NOTIFY_DONE;
298}
299
300struct notifier_block hdd_netdev_notifier = {
301 .notifier_call = hdd_netdev_notifier_call,
302};
303
304/*---------------------------------------------------------------------------
305 * Function definitions
306 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700307void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
308void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700309//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700310static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700311#ifndef MODULE
312/* current con_mode - used only for statically linked driver
313 * con_mode is changed by userspace to indicate a mode change which will
314 * result in calling the module exit and init functions. The module
315 * exit function will clean up based on the value of con_mode prior to it
316 * being changed by userspace. So curr_con_mode records the current con_mode
317 * for exit when con_mode becomes the next mode for init
318 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700319static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700320#endif
321
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800322/**---------------------------------------------------------------------------
323
324 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
325
326 Called immediately after the cfg.ini is read in order to configure
327 the desired trace levels.
328
329 \param - moduleId - module whose trace level is being configured
330 \param - bitmask - bitmask of log levels to be enabled
331
332 \return - void
333
334 --------------------------------------------------------------------------*/
335static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
336{
337 wpt_tracelevel level;
338
339 /* if the bitmask is the default value, then a bitmask was not
340 specified in cfg.ini, so leave the logging level alone (it
341 will remain at the "compiled in" default value) */
342 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
343 {
344 return;
345 }
346
347 /* a mask was specified. start by disabling all logging */
348 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
349
350 /* now cycle through the bitmask until all "set" bits are serviced */
351 level = VOS_TRACE_LEVEL_FATAL;
352 while (0 != bitmask)
353 {
354 if (bitmask & 1)
355 {
356 vos_trace_setValue(moduleId, level, 1);
357 }
358 level++;
359 bitmask >>= 1;
360 }
361}
362
363
Jeff Johnson295189b2012-06-20 16:38:30 -0700364/**---------------------------------------------------------------------------
365
366 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
367
368 Called immediately after the cfg.ini is read in order to configure
369 the desired trace levels in the WDI.
370
371 \param - moduleId - module whose trace level is being configured
372 \param - bitmask - bitmask of log levels to be enabled
373
374 \return - void
375
376 --------------------------------------------------------------------------*/
377static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
378{
379 wpt_tracelevel level;
380
381 /* if the bitmask is the default value, then a bitmask was not
382 specified in cfg.ini, so leave the logging level alone (it
383 will remain at the "compiled in" default value) */
384 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
385 {
386 return;
387 }
388
389 /* a mask was specified. start by disabling all logging */
390 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
391
392 /* now cycle through the bitmask until all "set" bits are serviced */
393 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
394 while (0 != bitmask)
395 {
396 if (bitmask & 1)
397 {
398 wpalTraceSetLevel(moduleId, level, 1);
399 }
400 level++;
401 bitmask >>= 1;
402 }
403}
Jeff Johnson295189b2012-06-20 16:38:30 -0700404
405int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
406{
407 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
408 hdd_priv_data_t priv_data;
409 tANI_U8 *command = NULL;
410 int ret = 0;
411
412 if (NULL == pAdapter)
413 {
414 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700415 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700416 ret = -ENODEV;
417 goto exit;
418 }
419
Jeff Johnsone7245742012-09-05 17:12:55 -0700420 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700421 {
422 ret = -EINVAL;
423 goto exit;
424 }
425
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -0700426 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
427 {
428 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
429 "%s:LOGP in Progress. Ignore!!!", __func__);
430 ret = -EBUSY;
431 goto exit;
432 }
433
Jeff Johnson295189b2012-06-20 16:38:30 -0700434 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
435 {
436 ret = -EFAULT;
437 goto exit;
438 }
439
440 command = kmalloc(priv_data.total_len, GFP_KERNEL);
441 if (!command)
442 {
443 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700444 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700445 ret = -ENOMEM;
446 goto exit;
447 }
448
449 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
450 {
451 ret = -EFAULT;
452 goto exit;
453 }
454
455 if ((SIOCDEVPRIVATE + 1) == cmd)
456 {
457 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
458
459 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700460 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700461
462 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
463 {
464 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
465 sizeof(tSirMacAddr)))
466 {
467 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700468 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700469 ret = -EFAULT;
470 }
471 }
Amar Singhal0974e402013-02-12 14:27:46 -0800472 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700473 {
Amar Singhal0974e402013-02-12 14:27:46 -0800474 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700475 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800476
Jeff Johnson295189b2012-06-20 16:38:30 -0700477 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800478
479 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700480 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700481 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800482 "%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 -0700483 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800484 ret = hdd_setBand_helper(dev, ptr);
485 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700486 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
487 {
488 char *country_code;
489
490 country_code = command + 8;
491 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
492 pAdapter, pHddCtx->pvosContext);
493 if( 0 != ret )
494 {
495 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
496 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
497
498 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700499 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800500#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
501 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
502 {
503 tANI_U8 *value = command;
504 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
505 tANI_U8 revision = 0;
506 eHalStatus status = eHAL_STATUS_SUCCESS;
507 v_REGDOMAIN_t regId;
508
509 status = hdd_parse_countryrev(value, countryCode, &revision);
510 if (eHAL_STATUS_SUCCESS != status)
511 {
512 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
513 "%s: Failed to parse country revision information", __func__);
514 ret = -EINVAL;
515 goto exit;
516 }
517
518 /* Validate country code */
519 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
520 if (eHAL_STATUS_SUCCESS != status)
521 {
522 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
523 "%s: Invalid country code %s", __func__, countryCode);
524 ret = -EINVAL;
525 goto exit;
526 }
527
528 /* Validate revision */
529 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
530 {
531 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
532 "%s: Invalid revision %d", __func__, revision);
533 ret = -EINVAL;
534 goto exit;
535 }
536
537 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
538 pAdapter, pHddCtx->pvosContext);
539 if (0 != ret)
540 {
541 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
542 "%s: SME Change Country code fail ret=%d", __func__, ret);
543 ret = -EINVAL;
544 goto exit;
545 }
546
547 if (0 == strncmp(countryCode, "KR", 2))
548 {
549 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
550 revision);
551 if (eHAL_STATUS_SUCCESS != status)
552 {
553 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
554 "%s: Failed to build valid channel list", __func__);
555 ret = -EINVAL;
556 goto exit;
557 }
558 }
559 }
560#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700561 /*
562 command should be a string having format
563 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
564 */
Amar Singhal0974e402013-02-12 14:27:46 -0800565 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700566 {
Amar Singhal0974e402013-02-12 14:27:46 -0800567 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700568
569 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700570 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700571
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800572 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700573 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800574 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
575 {
576 int suspend = 0;
577 tANI_U8 *ptr = (tANI_U8*)command + 15;
578
579 suspend = *ptr - '0';
580 hdd_set_wlan_suspend_mode(suspend);
581 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800582#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
583 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
584 {
585 tANI_U8 *value = command;
586 int rssi = 0;
587 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
588 eHalStatus status = eHAL_STATUS_SUCCESS;
589
590 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
591 value = value + 15;
592
593 sscanf(value, "%d", &rssi);
594 lookUpThreshold = abs(rssi);
595 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
596 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
597 {
598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
599 "Neighbor lookup threshold value %d is out of range"
600 " (Min: %d Max: %d)", lookUpThreshold,
601 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
602 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
603 ret = -EINVAL;
604 goto exit;
605 }
606
607 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
608 "%s: Received Command to Set Roam trigger"
609 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
610
611 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
612 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
613 if (eHAL_STATUS_SUCCESS != status)
614 {
615 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
616 "%s: Failed to set roam trigger, try again", __func__);
617 ret = -EPERM;
618 goto exit;
619 }
620
621 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
622 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
623 }
624 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
625 {
626 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
627 int rssi = (-1) * lookUpThreshold;
628 char extra[32];
629 tANI_U8 len = 0;
630
631 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
632 if (copy_to_user(priv_data.buf, &extra, len + 1))
633 {
634 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
635 "%s: failed to copy data to user buffer", __func__);
636 ret = -EFAULT;
637 goto exit;
638 }
639 }
640 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
641 {
642 tANI_U8 *value = command;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700643 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800644 /* input refresh period is in terms of seconds */
645 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
646 value = value + 18;
647 /* Convert the value from ascii to integer */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700648 ret = kstrtou16(value, 10, &neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800649 if (ret < 0)
650 {
651 /* If the input value is greater than max value of datatype, then also
652 kstrtou16 fails */
653 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
654 "%s: kstrtou16 failed ",
655 "Input value may be out of range[%d - %d]",
656 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700657 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
658 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800659 ret = -EINVAL;
660 goto exit;
661 }
662
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700663 neighborEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod * 1000;
664 if ((neighborEmptyScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
665 (neighborEmptyScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800666 {
667 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700668 "Neighbor empty scan results refresh period value %d is out of range"
669 " (Min: %d Max: %d)", neighborEmptyScanRefreshPeriod/1000,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700670 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
671 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800672 ret = -EINVAL;
673 goto exit;
674 }
675
676 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
677 "%s: Received Command to Set roam scan period"
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700678 " (Empty Scan refresh period) = %d", __func__, neighborEmptyScanRefreshPeriod/1000);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800679
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700680 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
681 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800682 }
683 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
684 {
685 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
686 char extra[32];
687 tANI_U8 len = 0;
688
689 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
690 /* Returned value is in units of seconds */
691 if (copy_to_user(priv_data.buf, &extra, len + 1))
692 {
693 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
694 "%s: failed to copy data to user buffer", __func__);
695 ret = -EFAULT;
696 goto exit;
697 }
698 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700699 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
700 {
701 tANI_U8 *value = command;
702 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
703 /* input refresh period is in terms of seconds */
704 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
705 value = value + 25;
706 /* Convert the value from ascii to integer */
707 ret = kstrtou16(value, 10, &neighborScanRefreshPeriod);
708 if (ret < 0)
709 {
710 /* If the input value is greater than max value of datatype, then also
711 kstrtou16 fails */
712 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
713 "%s: kstrtou16 failed ",
714 "Input value may be out of range[%d - %d]",
715 __func__,
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700716 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
717 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700718 ret = -EINVAL;
719 goto exit;
720 }
721
722 neighborScanRefreshPeriod = neighborScanRefreshPeriod * 1000;
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700723 if ((neighborScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
724 (neighborScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700725 {
726 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
727 "Neighbor scan results refresh period value %d is out of range"
728 " (Min: %d Max: %d)", neighborScanRefreshPeriod/1000,
729 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
730 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
731 ret = -EINVAL;
732 goto exit;
733 }
734
735 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
736 "%s: Received Command to Set roam scan refresh period"
737 " (Scan refresh period) = %d", __func__, neighborScanRefreshPeriod/1000);
738
739 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
740 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
741 }
742 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
743 {
744 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
745 char extra[32];
746 tANI_U8 len = 0;
747
748 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
749 /* Returned value is in units of seconds */
750 if (copy_to_user(priv_data.buf, &extra, len + 1))
751 {
752 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
753 "%s: failed to copy data to user buffer", __func__);
754 ret = -EFAULT;
755 goto exit;
756 }
757 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800758#endif
759#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
760 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
761 {
762 tANI_U8 *value = command;
763 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
764
765 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
766 value = value + 13;
767 /* Convert the value from ascii to integer */
768 ret = kstrtou8(value, 10, &roamRssiDiff);
769 if (ret < 0)
770 {
771 /* If the input value is greater than max value of datatype, then also
772 kstrtou8 fails */
773 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
774 "%s: kstrtou8 failed range [%d - %d]", __func__,
775 CFG_ROAM_RSSI_DIFF_MIN,
776 CFG_ROAM_RSSI_DIFF_MAX);
777 ret = -EINVAL;
778 goto exit;
779 }
780
781 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
782 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
783 {
784 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
785 "Roam rssi diff value %d is out of range"
786 " (Min: %d Max: %d)", roamRssiDiff,
787 CFG_ROAM_RSSI_DIFF_MIN,
788 CFG_ROAM_RSSI_DIFF_MAX);
789 ret = -EINVAL;
790 goto exit;
791 }
792
793 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
794 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
795
796 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
797 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
798 }
799 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
800 {
801 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
802 char extra[32];
803 tANI_U8 len = 0;
804
805 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
806 if (copy_to_user(priv_data.buf, &extra, len + 1))
807 {
808 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
809 "%s: failed to copy data to user buffer", __func__);
810 ret = -EFAULT;
811 goto exit;
812 }
813 }
814#endif
815#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
816 else if (strncmp(command, "GETBAND", 7) == 0)
817 {
818 int band = -1;
819 char extra[32];
820 tANI_U8 len = 0;
821 hdd_getBand_helper(pHddCtx, &band);
822
823 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
824 if (copy_to_user(priv_data.buf, &extra, len + 1))
825 {
826 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
827 "%s: failed to copy data to user buffer", __func__);
828 ret = -EFAULT;
829 goto exit;
830 }
831 }
832 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
833 {
834 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
835 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
836 tANI_U8 revision = 0;
837 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
838 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
839 char extra[32] = {0};
840 tANI_U8 len = 0;
841
842 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
843 {
844 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
845 "%s: failed to get country code", __func__);
846 ret = -EFAULT;
847 goto exit;
848 }
849 pBuf[uBufLen] = '\0';
850 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
851
852 if (0 == strncmp(pBuf, "KR", 2))
853 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
854 else
855 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
856
857 if (copy_to_user(priv_data.buf, &extra, len + 1))
858 {
859 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
860 "%s: failed to copy data to user buffer", __func__);
861 ret = -EFAULT;
862 goto exit;
863 }
864 }
865 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
866 {
867 tANI_U8 *value = command;
868 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
869 tANI_U8 numChannels = 0;
870 eHalStatus status = eHAL_STATUS_SUCCESS;
871
872 status = hdd_parse_channellist(value, ChannelList, &numChannels);
873 if (eHAL_STATUS_SUCCESS != status)
874 {
875 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
876 "%s: Failed to parse channel list information", __func__);
877 ret = -EINVAL;
878 goto exit;
879 }
880
881 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
882 {
883 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
884 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
885 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
886 ret = -EINVAL;
887 goto exit;
888 }
889 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
890 numChannels);
891 if (eHAL_STATUS_SUCCESS != status)
892 {
893 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
894 "%s: Failed to update channel list information", __func__);
895 ret = -EINVAL;
896 goto exit;
897 }
898 }
899 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
900 {
901 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
902 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -0700903 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800904 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -0700905 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800906
907 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
908 ChannelList, &numChannels ))
909 {
910 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
911 "%s: failed to get roam scan channel list", __func__);
912 ret = -EFAULT;
913 goto exit;
914 }
915 /* output channel list is of the format
916 [Number of roam scan channels][Channel1][Channel2]... */
917 /* copy the number of channels in the 0th index */
918 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
919 for (j = 0; (j < numChannels); j++)
920 {
921 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
922 }
923
924 if (copy_to_user(priv_data.buf, &extra, len + 1))
925 {
926 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
927 "%s: failed to copy data to user buffer", __func__);
928 ret = -EFAULT;
929 goto exit;
930 }
931 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700932 else if (strncmp(command, "GETCCXMODE", 10) == 0)
933 {
934 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
935 char extra[32];
936 tANI_U8 len = 0;
937
938 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
939 if (copy_to_user(priv_data.buf, &extra, len + 1))
940 {
941 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
942 "%s: failed to copy data to user buffer", __func__);
943 ret = -EFAULT;
944 goto exit;
945 }
946 }
947 else if (strncmp(command, "GETOKCMODE", 10) == 0)
948 {
949 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
950 char extra[32];
951 tANI_U8 len = 0;
952
953 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
954 if (copy_to_user(priv_data.buf, &extra, len + 1))
955 {
956 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
957 "%s: failed to copy data to user buffer", __func__);
958 ret = -EFAULT;
959 goto exit;
960 }
961 }
962 else if (strncmp(command, "GETFASTROAM", 10) == 0)
963 {
964 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
965 char extra[32];
966 tANI_U8 len = 0;
967
968 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
969 if (copy_to_user(priv_data.buf, &extra, len + 1))
970 {
971 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
972 "%s: failed to copy data to user buffer", __func__);
973 ret = -EFAULT;
974 goto exit;
975 }
976 }
977 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
978 {
979 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
980 char extra[32];
981 tANI_U8 len = 0;
982
983 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
984 if (copy_to_user(priv_data.buf, &extra, len + 1))
985 {
986 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
987 "%s: failed to copy data to user buffer", __func__);
988 ret = -EFAULT;
989 goto exit;
990 }
991 }
992 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
993 {
994 tANI_U8 *value = command;
995 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
996
997 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
998 value = value + 26;
999 /* Convert the value from ascii to integer */
1000 ret = kstrtou8(value, 10, &minTime);
1001 if (ret < 0)
1002 {
1003 /* If the input value is greater than max value of datatype, then also
1004 kstrtou8 fails */
1005 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1006 "%s: kstrtou8 failed range [%d - %d]", __func__,
1007 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1008 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1009 ret = -EINVAL;
1010 goto exit;
1011 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001012 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1013 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1014 {
1015 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1016 "scan min channel time value %d is out of range"
1017 " (Min: %d Max: %d)", minTime,
1018 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1019 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1020 ret = -EINVAL;
1021 goto exit;
1022 }
1023
1024 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1025 "%s: Received Command to change channel min time = %d", __func__, minTime);
1026
1027 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1028 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1029 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001030 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1031 {
1032 tANI_U8 *value = command;
1033 tANI_U8 channel = 0;
1034 tANI_U8 dwellTime = 0;
1035 tANI_U8 bufLen = 0;
1036 tANI_U8 *buf = NULL;
1037 tSirMacAddr targetApBssid;
1038 eHalStatus status = eHAL_STATUS_SUCCESS;
1039 struct ieee80211_channel chan;
1040 tANI_U8 finalLen = 0;
1041 tANI_U8 *finalBuf = NULL;
1042 tANI_U8 temp = 0;
1043 u64 cookie;
1044 hdd_station_ctx_t *pHddStaCtx = NULL;
1045 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1046
1047 /* if not associated, no need to send action frame */
1048 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1049 {
1050 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1051 ret = -EINVAL;
1052 goto exit;
1053 }
1054
1055 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1056 &dwellTime, &buf, &bufLen);
1057 if (eHAL_STATUS_SUCCESS != status)
1058 {
1059 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1060 "%s: Failed to parse send action frame data", __func__);
1061 ret = -EINVAL;
1062 goto exit;
1063 }
1064
1065 /* if the target bssid is different from currently associated AP,
1066 then no need to send action frame */
1067 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1068 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1069 {
1070 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1071 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001072 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001073 goto exit;
1074 }
1075
1076 /* if the channel number is different from operating channel then
1077 no need to send action frame */
1078 if (channel != pHddStaCtx->conn_info.operationChannel)
1079 {
1080 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1081 "%s: channel(%d) is different from operating channel(%d)",
1082 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1083 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001084 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001085 goto exit;
1086 }
1087 chan.center_freq = sme_ChnToFreq(channel);
1088
1089 finalLen = bufLen + 24;
1090 finalBuf = vos_mem_malloc(finalLen);
1091 if (NULL == finalBuf)
1092 {
1093 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1094 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001095 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001096 goto exit;
1097 }
1098 vos_mem_zero(finalBuf, finalLen);
1099
1100 /* Fill subtype */
1101 temp = SIR_MAC_MGMT_ACTION << 4;
1102 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1103
1104 /* Fill type */
1105 temp = SIR_MAC_MGMT_FRAME;
1106 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1107
1108 /* Fill destination address (bssid of the AP) */
1109 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1110
1111 /* Fill BSSID (STA mac address) */
1112 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1113
1114 /* Fill source address (STA mac address) */
1115 vos_mem_copy(finalBuf + 16, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1116
1117 /* Fill received buffer from 24th address */
1118 vos_mem_copy(finalBuf + 24, buf, bufLen);
1119
Jeff Johnson11c33152013-04-16 17:52:40 -07001120 /* done with the parsed buffer */
1121 vos_mem_free(buf);
1122
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001123 wlan_hdd_action( NULL, dev, &chan, 0, NL80211_CHAN_HT20,
1124 1, dwellTime, finalBuf, finalLen, 1,
1125 1, &cookie );
1126 vos_mem_free(finalBuf);
1127 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001128 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1129 {
1130 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1131 char extra[32];
1132 tANI_U8 len = 0;
1133
1134 /* value is interms of msec */
1135 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1136 if (copy_to_user(priv_data.buf, &extra, len + 1))
1137 {
1138 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1139 "%s: failed to copy data to user buffer", __func__);
1140 ret = -EFAULT;
1141 goto exit;
1142 }
1143 }
1144 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1145 {
1146 tANI_U8 *value = command;
1147 tANI_U8 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
1148
1149 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1150 value = value + 19;
1151 /* Convert the value from ascii to integer */
1152 ret = kstrtou8(value, 10, &maxTime);
1153 if (ret < 0)
1154 {
1155 /* If the input value is greater than max value of datatype, then also
1156 kstrtou8 fails */
1157 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1158 "%s: kstrtou8 failed range [%d - %d]", __func__,
1159 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1160 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1161 ret = -EINVAL;
1162 goto exit;
1163 }
1164
1165 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1166 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1167 {
1168 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1169 "lfr mode value %d is out of range"
1170 " (Min: %d Max: %d)", maxTime,
1171 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1172 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1173 ret = -EINVAL;
1174 goto exit;
1175 }
1176
1177 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1178 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1179
1180 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
1181 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1182 }
1183 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1184 {
1185 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1186 char extra[32];
1187 tANI_U8 len = 0;
1188
1189 /* value is interms of msec */
1190 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1191 if (copy_to_user(priv_data.buf, &extra, len + 1))
1192 {
1193 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1194 "%s: failed to copy data to user buffer", __func__);
1195 ret = -EFAULT;
1196 goto exit;
1197 }
1198 }
1199 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1200 {
1201 tANI_U8 *value = command;
1202 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1203
1204 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1205 value = value + 16;
1206 /* Convert the value from ascii to integer */
1207 ret = kstrtou16(value, 10, &val);
1208 if (ret < 0)
1209 {
1210 /* If the input value is greater than max value of datatype, then also
1211 kstrtou16 fails */
1212 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1213 "%s: kstrtou16 failed range [%d - %d]", __func__,
1214 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1215 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1216 ret = -EINVAL;
1217 goto exit;
1218 }
1219
1220 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1221 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1222 {
1223 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1224 "scan home time value %d is out of range"
1225 " (Min: %d Max: %d)", val,
1226 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1227 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1228 ret = -EINVAL;
1229 goto exit;
1230 }
1231
1232 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1233 "%s: Received Command to change scan home time = %d", __func__, val);
1234
1235 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1236 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1237 }
1238 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1239 {
1240 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1241 char extra[32];
1242 tANI_U8 len = 0;
1243
1244 /* value is interms of msec */
1245 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1246 if (copy_to_user(priv_data.buf, &extra, len + 1))
1247 {
1248 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1249 "%s: failed to copy data to user buffer", __func__);
1250 ret = -EFAULT;
1251 goto exit;
1252 }
1253 }
1254 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1255 {
1256 tANI_U8 *value = command;
1257 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1258
1259 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1260 value = value + 17;
1261 /* Convert the value from ascii to integer */
1262 ret = kstrtou8(value, 10, &val);
1263 if (ret < 0)
1264 {
1265 /* If the input value is greater than max value of datatype, then also
1266 kstrtou8 fails */
1267 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1268 "%s: kstrtou8 failed range [%d - %d]", __func__,
1269 CFG_ROAM_INTRA_BAND_MIN,
1270 CFG_ROAM_INTRA_BAND_MAX);
1271 ret = -EINVAL;
1272 goto exit;
1273 }
1274
1275 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1276 (val > CFG_ROAM_INTRA_BAND_MAX))
1277 {
1278 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1279 "intra band mode value %d is out of range"
1280 " (Min: %d Max: %d)", val,
1281 CFG_ROAM_INTRA_BAND_MIN,
1282 CFG_ROAM_INTRA_BAND_MAX);
1283 ret = -EINVAL;
1284 goto exit;
1285 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001286 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1287 "%s: Received Command to change intra band = %d", __func__, val);
1288
1289 pHddCtx->cfg_ini->nRoamIntraBand = val;
1290 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1291 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001292 else if (strncmp(command, "SETWESMODE", 10) == 0)
1293 {
1294 tANI_U8 *value = command;
1295 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
1296
1297 /* Move pointer to ahead of SETWESMODE<delimiter> */
1298 value = value + 11;
1299 /* Convert the value from ascii to integer */
1300 ret = kstrtou8(value, 10, &wesMode);
1301 if (ret < 0)
1302 {
1303 /* If the input value is greater than max value of datatype, then also
1304 kstrtou8 fails */
1305 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1306 "%s: kstrtou8 failed range [%d - %d]", __func__,
1307 CFG_ENABLE_WES_MODE_NAME_MIN,
1308 CFG_ENABLE_WES_MODE_NAME_MAX);
1309 ret = -EINVAL;
1310 goto exit;
1311 }
1312
1313 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
1314 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
1315 {
1316 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1317 "WES Mode value %d is out of range"
1318 " (Min: %d Max: %d)", wesMode,
1319 CFG_ENABLE_WES_MODE_NAME_MIN,
1320 CFG_ENABLE_WES_MODE_NAME_MAX);
1321 ret = -EINVAL;
1322 goto exit;
1323 }
1324 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1325 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
1326
1327 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
1328 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
1329 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001330 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1331 {
1332 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1333 char extra[32];
1334 tANI_U8 len = 0;
1335
1336 /* value is interms of msec */
1337 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1338 if (copy_to_user(priv_data.buf, &extra, len + 1))
1339 {
1340 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1341 "%s: failed to copy data to user buffer", __func__);
1342 ret = -EFAULT;
1343 goto exit;
1344 }
1345 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001346 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
1347 {
1348 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
1349 char extra[32];
1350 tANI_U8 len = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001351
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001352 len = snprintf(extra, sizeof(extra), "%s %d", command, wesMode);
1353 if (copy_to_user(priv_data.buf, &extra, len + 1))
1354 {
1355 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1356 "%s: failed to copy data to user buffer", __func__);
1357 ret = -EFAULT;
1358 goto exit;
1359 }
1360 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001361#endif
1362#ifdef FEATURE_WLAN_LFR
1363 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1364 {
1365 tANI_U8 *value = command;
1366 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1367
1368 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1369 value = value + 12;
1370 /* Convert the value from ascii to integer */
1371 ret = kstrtou8(value, 10, &lfrMode);
1372 if (ret < 0)
1373 {
1374 /* If the input value is greater than max value of datatype, then also
1375 kstrtou8 fails */
1376 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1377 "%s: kstrtou8 failed range [%d - %d]", __func__,
1378 CFG_LFR_FEATURE_ENABLED_MIN,
1379 CFG_LFR_FEATURE_ENABLED_MAX);
1380 ret = -EINVAL;
1381 goto exit;
1382 }
1383
1384 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1385 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1386 {
1387 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1388 "lfr mode value %d is out of range"
1389 " (Min: %d Max: %d)", lfrMode,
1390 CFG_LFR_FEATURE_ENABLED_MIN,
1391 CFG_LFR_FEATURE_ENABLED_MAX);
1392 ret = -EINVAL;
1393 goto exit;
1394 }
1395
1396 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1397 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1398
1399 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1400 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1401 }
1402#endif
1403#ifdef WLAN_FEATURE_VOWIFI_11R
1404 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1405 {
1406 tANI_U8 *value = command;
1407 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1408
1409 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1410 value = value + 18;
1411 /* Convert the value from ascii to integer */
1412 ret = kstrtou8(value, 10, &ft);
1413 if (ret < 0)
1414 {
1415 /* If the input value is greater than max value of datatype, then also
1416 kstrtou8 fails */
1417 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1418 "%s: kstrtou8 failed range [%d - %d]", __func__,
1419 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1420 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1421 ret = -EINVAL;
1422 goto exit;
1423 }
1424
1425 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1426 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1427 {
1428 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1429 "ft mode value %d is out of range"
1430 " (Min: %d Max: %d)", ft,
1431 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1432 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1433 ret = -EINVAL;
1434 goto exit;
1435 }
1436
1437 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1438 "%s: Received Command to change ft mode = %d", __func__, ft);
1439
1440 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1441 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1442 }
1443#endif
1444#ifdef FEATURE_WLAN_CCX
1445 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1446 {
1447 tANI_U8 *value = command;
1448 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1449
1450 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1451 value = value + 11;
1452 /* Convert the value from ascii to integer */
1453 ret = kstrtou8(value, 10, &ccxMode);
1454 if (ret < 0)
1455 {
1456 /* If the input value is greater than max value of datatype, then also
1457 kstrtou8 fails */
1458 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1459 "%s: kstrtou8 failed range [%d - %d]", __func__,
1460 CFG_CCX_FEATURE_ENABLED_MIN,
1461 CFG_CCX_FEATURE_ENABLED_MAX);
1462 ret = -EINVAL;
1463 goto exit;
1464 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001465 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1466 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1467 {
1468 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1469 "Ccx mode value %d is out of range"
1470 " (Min: %d Max: %d)", ccxMode,
1471 CFG_CCX_FEATURE_ENABLED_MIN,
1472 CFG_CCX_FEATURE_ENABLED_MAX);
1473 ret = -EINVAL;
1474 goto exit;
1475 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001476 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1477 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1478
1479 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1480 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1481 }
1482#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001483 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1484 {
1485 tANI_U8 *value = command;
1486 tANI_BOOLEAN roamScanControl = 0;
1487
1488 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1489 value = value + 19;
1490 /* Convert the value from ascii to integer */
1491 ret = kstrtou8(value, 10, &roamScanControl);
1492 if (ret < 0)
1493 {
1494 /* If the input value is greater than max value of datatype, then also
1495 kstrtou8 fails */
1496 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1497 "%s: kstrtou8 failed ", __func__);
1498 ret = -EINVAL;
1499 goto exit;
1500 }
1501
1502 if (0 != roamScanControl)
1503 {
1504 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1505 "roam scan control invalid value = %d",
1506 roamScanControl);
1507 ret = -EINVAL;
1508 goto exit;
1509 }
1510 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1511 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1512
1513 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1514 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001515#ifdef FEATURE_WLAN_OKC
1516 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1517 {
1518 tANI_U8 *value = command;
1519 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1520
1521 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1522 value = value + 11;
1523 /* Convert the value from ascii to integer */
1524 ret = kstrtou8(value, 10, &okcMode);
1525 if (ret < 0)
1526 {
1527 /* If the input value is greater than max value of datatype, then also
1528 kstrtou8 fails */
1529 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1530 "%s: kstrtou8 failed range [%d - %d]", __func__,
1531 CFG_OKC_FEATURE_ENABLED_MIN,
1532 CFG_OKC_FEATURE_ENABLED_MAX);
1533 ret = -EINVAL;
1534 goto exit;
1535 }
1536
1537 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1538 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1539 {
1540 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1541 "Okc mode value %d is out of range"
1542 " (Min: %d Max: %d)", okcMode,
1543 CFG_OKC_FEATURE_ENABLED_MIN,
1544 CFG_OKC_FEATURE_ENABLED_MAX);
1545 ret = -EINVAL;
1546 goto exit;
1547 }
1548
1549 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1550 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1551
1552 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1553 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001554 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1555 {
1556 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1557 char extra[32];
1558 tANI_U8 len = 0;
1559
1560 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1561 if (copy_to_user(priv_data.buf, &extra, len + 1))
1562 {
1563 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1564 "%s: failed to copy data to user buffer", __func__);
1565 ret = -EFAULT;
1566 goto exit;
1567 }
1568 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001569#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001570 else {
1571 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
1572 __func__, command);
1573 }
1574
Jeff Johnson295189b2012-06-20 16:38:30 -07001575 }
1576exit:
1577 if (command)
1578 {
1579 kfree(command);
1580 }
1581 return ret;
1582}
1583
Srinivas Girigowdade697412013-02-14 16:31:48 -08001584#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1585void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
1586{
1587 eCsrBand band = -1;
1588 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
1589 switch (band)
1590 {
1591 case eCSR_BAND_ALL:
1592 *pBand = WLAN_HDD_UI_BAND_AUTO;
1593 break;
1594
1595 case eCSR_BAND_24:
1596 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
1597 break;
1598
1599 case eCSR_BAND_5G:
1600 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
1601 break;
1602
1603 default:
1604 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
1605 *pBand = -1;
1606 break;
1607 }
1608}
1609
1610/**---------------------------------------------------------------------------
1611
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001612 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
1613
1614 This function parses the send action frame data passed in the format
1615 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
1616
1617 \param - pValue Pointer to input country code revision
1618 \param - pTargetApBssid Pointer to target Ap bssid
1619 \param - pChannel Pointer to the Target AP channel
1620 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
1621 \param - pBuf Pointer to data
1622 \param - pBufLen Pointer to data length
1623
1624 \return - 0 for success non-zero for failure
1625
1626 --------------------------------------------------------------------------*/
1627VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
1628 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
1629{
1630 tANI_U8 *inPtr = pValue;
1631 tANI_U8 *dataEnd;
1632 int tempInt;
1633 int j = 0;
1634 int i = 0;
1635 int v = 0;
1636 tANI_U8 tempBuf[32];
1637 tANI_U8 tempByte = 0;
1638
1639 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1640 /*no argument after the command*/
1641 if (NULL == inPtr)
1642 {
1643 return -EINVAL;
1644 }
1645
1646 /*no space after the command*/
1647 else if (SPACE_ASCII_VALUE != *inPtr)
1648 {
1649 return -EINVAL;
1650 }
1651
1652 /*removing empty spaces*/
1653 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1654
1655 /*no argument followed by spaces*/
1656 if ('\0' == *inPtr)
1657 {
1658 return -EINVAL;
1659 }
1660
1661 /*getting the first argument ie the target AP bssid */
1662 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
1663 {
1664 return -EINVAL;
1665 }
1666 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
1667 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
1668 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
1669
1670 /* point to the next argument */
1671 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1672 /*no argument after the command*/
1673 if (NULL == inPtr) return -EINVAL;
1674
1675 /*removing empty spaces*/
1676 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1677
1678 /*no argument followed by spaces*/
1679 if ('\0' == *inPtr)
1680 {
1681 return -EINVAL;
1682 }
1683
1684 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07001685 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001686 v = kstrtos32(tempBuf, 10, &tempInt);
1687 if ( v < 0) return -EINVAL;
1688
1689 *pChannel = tempInt;
1690
1691 /* point to the next argument */
1692 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1693 /*no argument after the command*/
1694 if (NULL == inPtr) return -EINVAL;
1695 /*removing empty spaces*/
1696 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1697
1698 /*no argument followed by spaces*/
1699 if ('\0' == *inPtr)
1700 {
1701 return -EINVAL;
1702 }
1703
1704 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07001705 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001706 v = kstrtos32(tempBuf, 10, &tempInt);
1707 if ( v < 0) return -EINVAL;
1708
1709 *pDwellTime = tempInt;
1710
1711 /* point to the next argument */
1712 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1713 /*no argument after the command*/
1714 if (NULL == inPtr) return -EINVAL;
1715 /*removing empty spaces*/
1716 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1717
1718 /*no argument followed by spaces*/
1719 if ('\0' == *inPtr)
1720 {
1721 return -EINVAL;
1722 }
1723
1724 /* find the length of data */
1725 dataEnd = inPtr;
1726 while(('\0' != *dataEnd) )
1727 {
1728 dataEnd++;
1729 ++(*pBufLen);
1730 }
1731 if ( *pBufLen <= 0) return -EINVAL;
1732
1733 *pBuf = vos_mem_malloc(sizeof(*pBufLen));
1734 if (NULL == *pBuf)
1735 {
1736 hddLog(VOS_TRACE_LEVEL_FATAL,
1737 "%s: vos_mem_alloc failed ", __func__);
1738 return -EINVAL;
1739 }
1740
1741 /* the buffer received from the upper layer is character buffer,
1742 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
1743 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
1744 and f0 in 3rd location */
1745 for (i = 0, j = 0; j < *pBufLen; j += 2)
1746 {
1747 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
1748 (*pBuf)[i++] = tempByte;
1749 }
1750 *pBufLen = i;
1751 return VOS_STATUS_SUCCESS;
1752}
1753
1754#endif
1755/**---------------------------------------------------------------------------
1756
Srinivas Girigowdade697412013-02-14 16:31:48 -08001757 \brief hdd_parse_countryrev() - HDD Parse country code revision
1758
1759 This function parses the country code revision passed in the format
1760 SETCOUNTRYREV<space><Country code><space>revision
1761
1762 \param - pValue Pointer to input country code revision
1763 \param - pCountryCode Pointer to local output array to record country code
1764 \param - pRevision Pointer to store revision integer number
1765
1766 \return - 0 for success non-zero for failure
1767
1768 --------------------------------------------------------------------------*/
1769VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
1770{
1771 tANI_U8 *inPtr = pValue;
1772 int tempInt;
1773
1774 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1775 /*no argument after the command*/
1776 if (NULL == inPtr)
1777 {
1778 return -EINVAL;
1779 }
1780
1781 /*no space after the command*/
1782 else if (SPACE_ASCII_VALUE != *inPtr)
1783 {
1784 return -EINVAL;
1785 }
1786
1787 /*removing empty spaces*/
1788 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
1789
1790 /*no argument followed by spaces*/
1791 if ('\0' == *inPtr)
1792 {
1793 return -EINVAL;
1794 }
1795
1796 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07001797 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001798
1799 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1800 "Country code is : %s", pCountryCode);
1801
1802 /*inPtr pointing to the beginning of first space after country code */
1803 inPtr = strpbrk( inPtr, " " );
1804 /*no revision number after the country code argument */
1805 if (NULL == inPtr)
1806 {
1807 return -EINVAL;
1808 }
1809
1810 inPtr++;
1811
1812 /*removing empty space*/
1813 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1814
1815 /*no channel list after the number of channels argument and spaces*/
1816 if (0 == strncmp(pCountryCode, "KR", 2))
1817 {
1818 if ('\0' == *inPtr)
1819 {
1820 return -EINVAL;
1821 }
1822
1823 sscanf(inPtr, "%d", &tempInt);
1824 *pRevision = tempInt;
1825 }
1826 else
1827 {
1828 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1829 "Revision input is required only for Country KR");
1830 return -EINVAL;
1831 }
1832 return VOS_STATUS_SUCCESS;
1833}
1834
1835/**---------------------------------------------------------------------------
1836
1837 \brief hdd_parse_channellist() - HDD Parse channel list
1838
1839 This function parses the channel list passed in the format
1840 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001841 if the Number of channels (N) does not match with the actual number of channels passed
1842 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
1843 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
1844 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
1845 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08001846
1847 \param - pValue Pointer to input channel list
1848 \param - ChannelList Pointer to local output array to record channel list
1849 \param - pNumChannels Pointer to number of roam scan channels
1850
1851 \return - 0 for success non-zero for failure
1852
1853 --------------------------------------------------------------------------*/
1854VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
1855{
1856 tANI_U8 *inPtr = pValue;
1857 int tempInt;
1858 int j = 0;
1859 int v = 0;
1860 char buf[32];
1861
1862 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1863 /*no argument after the command*/
1864 if (NULL == inPtr)
1865 {
1866 return -EINVAL;
1867 }
1868
1869 /*no space after the command*/
1870 else if (SPACE_ASCII_VALUE != *inPtr)
1871 {
1872 return -EINVAL;
1873 }
1874
1875 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001876 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001877
1878 /*no argument followed by spaces*/
1879 if ('\0' == *inPtr)
1880 {
1881 return -EINVAL;
1882 }
1883
1884 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07001885 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001886 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001887 if ((v < 0) ||
1888 (tempInt <= 0) ||
1889 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
1890 {
1891 return -EINVAL;
1892 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001893
1894 *pNumChannels = tempInt;
1895
1896 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1897 "Number of channels are: %d", *pNumChannels);
1898
1899 for (j = 0; j < (*pNumChannels); j++)
1900 {
1901 /*inPtr pointing to the beginning of first space after number of channels*/
1902 inPtr = strpbrk( inPtr, " " );
1903 /*no channel list after the number of channels argument*/
1904 if (NULL == inPtr)
1905 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001906 if (0 != j)
1907 {
1908 *pNumChannels = j;
1909 return VOS_STATUS_SUCCESS;
1910 }
1911 else
1912 {
1913 return -EINVAL;
1914 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001915 }
1916
1917 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001918 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001919
1920 /*no channel list after the number of channels argument and spaces*/
1921 if ( '\0' == *inPtr )
1922 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001923 if (0 != j)
1924 {
1925 *pNumChannels = j;
1926 return VOS_STATUS_SUCCESS;
1927 }
1928 else
1929 {
1930 return -EINVAL;
1931 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001932 }
1933
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001934 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001935 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001936 if ((v < 0) ||
1937 (tempInt <= 0) ||
1938 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
1939 {
1940 return -EINVAL;
1941 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001942 pChannelList[j] = tempInt;
1943
1944 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1945 "Channel %d added to preferred channel list",
1946 pChannelList[j] );
1947 }
1948
Srinivas Girigowdade697412013-02-14 16:31:48 -08001949 return VOS_STATUS_SUCCESS;
1950}
1951
Jeff Johnson295189b2012-06-20 16:38:30 -07001952/**---------------------------------------------------------------------------
1953
1954 \brief hdd_open() - HDD Open function
1955
1956 This is called in response to ifconfig up
1957
1958 \param - dev Pointer to net_device structure
1959
1960 \return - 0 for success non-zero for failure
1961
1962 --------------------------------------------------------------------------*/
1963int hdd_open (struct net_device *dev)
1964{
1965 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1966 hdd_context_t *pHddCtx;
1967 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1968 VOS_STATUS status;
1969 v_BOOL_t in_standby = TRUE;
1970
1971 if (NULL == pAdapter)
1972 {
1973 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001974 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001975 return -ENODEV;
1976 }
1977
1978 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1979 if (NULL == pHddCtx)
1980 {
1981 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001982 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001983 return -ENODEV;
1984 }
1985
1986 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1987 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1988 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07001989 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
1990 {
1991 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
1992 __func__, pAdapter->device_mode);
1993 in_standby = FALSE;
1994 break;
1995 }
1996 else
1997 {
1998 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1999 pAdapterNode = pNext;
2000 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002001 }
2002
2003 if (TRUE == in_standby)
2004 {
2005 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2006 {
2007 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2008 "wlan out of power save", __func__);
2009 return -EINVAL;
2010 }
2011 }
2012
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002013 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002014 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2015 {
2016 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002017 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002018 /* Enable TX queues only when we are connected */
2019 netif_tx_start_all_queues(dev);
2020 }
2021
2022 return 0;
2023}
2024
2025int hdd_mon_open (struct net_device *dev)
2026{
2027 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2028
2029 if(pAdapter == NULL) {
2030 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002031 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002032 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002033 }
2034
2035 netif_start_queue(dev);
2036
2037 return 0;
2038}
2039/**---------------------------------------------------------------------------
2040
2041 \brief hdd_stop() - HDD stop function
2042
2043 This is called in response to ifconfig down
2044
2045 \param - dev Pointer to net_device structure
2046
2047 \return - 0 for success non-zero for failure
2048
2049 --------------------------------------------------------------------------*/
2050
2051int hdd_stop (struct net_device *dev)
2052{
2053 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2054 hdd_context_t *pHddCtx;
2055 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2056 VOS_STATUS status;
2057 v_BOOL_t enter_standby = TRUE;
2058
2059 ENTER();
2060
2061 if (NULL == pAdapter)
2062 {
2063 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002064 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002065 return -ENODEV;
2066 }
2067
2068 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2069 if (NULL == pHddCtx)
2070 {
2071 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002072 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002073 return -ENODEV;
2074 }
2075
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002076 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002077 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2078 netif_tx_disable(pAdapter->dev);
2079 netif_carrier_off(pAdapter->dev);
2080
2081
2082 /* SoftAP ifaces should never go in power save mode
2083 making sure same here. */
2084 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2085 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002086 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002087 )
2088 {
2089 /* SoftAP mode, so return from here */
2090 EXIT();
2091 return 0;
2092 }
2093
2094 /* Find if any iface is up then
2095 if any iface is up then can't put device to sleep/ power save mode. */
2096 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2097 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2098 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002099 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2100 {
2101 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
2102 "put device to sleep", __func__, pAdapter->device_mode);
2103 enter_standby = FALSE;
2104 break;
2105 }
2106 else
2107 {
2108 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2109 pAdapterNode = pNext;
2110 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002111 }
2112
2113 if (TRUE == enter_standby)
2114 {
2115 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2116 "entering standby", __func__);
2117 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2118 {
2119 /*log and return success*/
2120 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2121 "wlan in power save", __func__);
2122 }
2123 }
2124
2125 EXIT();
2126 return 0;
2127}
2128
2129/**---------------------------------------------------------------------------
2130
2131 \brief hdd_uninit() - HDD uninit function
2132
2133 This is called during the netdev unregister to uninitialize all data
2134associated with the device
2135
2136 \param - dev Pointer to net_device structure
2137
2138 \return - void
2139
2140 --------------------------------------------------------------------------*/
2141static void hdd_uninit (struct net_device *dev)
2142{
2143 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2144
2145 ENTER();
2146
2147 do
2148 {
2149 if (NULL == pAdapter)
2150 {
2151 hddLog(VOS_TRACE_LEVEL_FATAL,
2152 "%s: NULL pAdapter", __func__);
2153 break;
2154 }
2155
2156 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2157 {
2158 hddLog(VOS_TRACE_LEVEL_FATAL,
2159 "%s: Invalid magic", __func__);
2160 break;
2161 }
2162
2163 if (NULL == pAdapter->pHddCtx)
2164 {
2165 hddLog(VOS_TRACE_LEVEL_FATAL,
2166 "%s: NULL pHddCtx", __func__);
2167 break;
2168 }
2169
2170 if (dev != pAdapter->dev)
2171 {
2172 hddLog(VOS_TRACE_LEVEL_FATAL,
2173 "%s: Invalid device reference", __func__);
2174 /* we haven't validated all cases so let this go for now */
2175 }
2176
2177 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2178
2179 /* after uninit our adapter structure will no longer be valid */
2180 pAdapter->dev = NULL;
2181 pAdapter->magic = 0;
2182 } while (0);
2183
2184 EXIT();
2185}
2186
2187/**---------------------------------------------------------------------------
2188
2189 \brief hdd_release_firmware() -
2190
2191 This function calls the release firmware API to free the firmware buffer.
2192
2193 \param - pFileName Pointer to the File Name.
2194 pCtx - Pointer to the adapter .
2195
2196
2197 \return - 0 for success, non zero for failure
2198
2199 --------------------------------------------------------------------------*/
2200
2201VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2202{
2203 VOS_STATUS status = VOS_STATUS_SUCCESS;
2204 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2205 ENTER();
2206
2207
2208 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2209
2210 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2211
2212 if(pHddCtx->fw) {
2213 release_firmware(pHddCtx->fw);
2214 pHddCtx->fw = NULL;
2215 }
2216 else
2217 status = VOS_STATUS_E_FAILURE;
2218 }
2219 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2220 if(pHddCtx->nv) {
2221 release_firmware(pHddCtx->nv);
2222 pHddCtx->nv = NULL;
2223 }
2224 else
2225 status = VOS_STATUS_E_FAILURE;
2226
2227 }
2228
2229 EXIT();
2230 return status;
2231}
2232
2233/**---------------------------------------------------------------------------
2234
2235 \brief hdd_request_firmware() -
2236
2237 This function reads the firmware file using the request firmware
2238 API and returns the the firmware data and the firmware file size.
2239
2240 \param - pfileName - Pointer to the file name.
2241 - pCtx - Pointer to the adapter .
2242 - ppfw_data - Pointer to the pointer of the firmware data.
2243 - pSize - Pointer to the file size.
2244
2245 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2246
2247 --------------------------------------------------------------------------*/
2248
2249
2250VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2251{
2252 int status;
2253 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2254 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2255 ENTER();
2256
2257 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2258
2259 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2260
2261 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2262 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2263 __func__, pfileName);
2264 retval = VOS_STATUS_E_FAILURE;
2265 }
2266
2267 else {
2268 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2269 *pSize = pHddCtx->fw->size;
2270 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2271 __func__, *pSize);
2272 }
2273 }
2274 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2275
2276 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2277
2278 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2279 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2280 __func__, pfileName);
2281 retval = VOS_STATUS_E_FAILURE;
2282 }
2283
2284 else {
2285 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2286 *pSize = pHddCtx->nv->size;
2287 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2288 __func__, *pSize);
2289 }
2290 }
2291
2292 EXIT();
2293 return retval;
2294}
2295/**---------------------------------------------------------------------------
2296 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2297
2298 This is the function invoked by SME to inform the result of a full power
2299 request issued by HDD
2300
2301 \param - callbackcontext - Pointer to cookie
2302 status - result of request
2303
2304 \return - None
2305
2306--------------------------------------------------------------------------*/
2307void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2308{
2309 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2310
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002311 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002312 if(&pHddCtx->full_pwr_comp_var)
2313 {
2314 complete(&pHddCtx->full_pwr_comp_var);
2315 }
2316}
2317
2318/**---------------------------------------------------------------------------
2319
2320 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2321
2322 This is the function invoked by SME to inform the result of BMPS
2323 request issued by HDD
2324
2325 \param - callbackcontext - Pointer to cookie
2326 status - result of request
2327
2328 \return - None
2329
2330--------------------------------------------------------------------------*/
2331void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2332{
2333
2334 struct completion *completion_var = (struct completion*) callbackContext;
2335
2336 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2337 if(completion_var != NULL)
2338 {
2339 complete(completion_var);
2340 }
2341}
2342
2343/**---------------------------------------------------------------------------
2344
2345 \brief hdd_get_cfg_file_size() -
2346
2347 This function reads the configuration file using the request firmware
2348 API and returns the configuration file size.
2349
2350 \param - pCtx - Pointer to the adapter .
2351 - pFileName - Pointer to the file name.
2352 - pBufSize - Pointer to the buffer size.
2353
2354 \return - 0 for success, non zero for failure
2355
2356 --------------------------------------------------------------------------*/
2357
2358VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2359{
2360 int status;
2361 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2362
2363 ENTER();
2364
2365 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2366
2367 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2368 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2369 status = VOS_STATUS_E_FAILURE;
2370 }
2371 else {
2372 *pBufSize = pHddCtx->fw->size;
2373 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2374 release_firmware(pHddCtx->fw);
2375 pHddCtx->fw = NULL;
2376 }
2377
2378 EXIT();
2379 return VOS_STATUS_SUCCESS;
2380}
2381
2382/**---------------------------------------------------------------------------
2383
2384 \brief hdd_read_cfg_file() -
2385
2386 This function reads the configuration file using the request firmware
2387 API and returns the cfg data and the buffer size of the configuration file.
2388
2389 \param - pCtx - Pointer to the adapter .
2390 - pFileName - Pointer to the file name.
2391 - pBuffer - Pointer to the data buffer.
2392 - pBufSize - Pointer to the buffer size.
2393
2394 \return - 0 for success, non zero for failure
2395
2396 --------------------------------------------------------------------------*/
2397
2398VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2399 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2400{
2401 int status;
2402 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2403
2404 ENTER();
2405
2406 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2407
2408 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2409 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2410 return VOS_STATUS_E_FAILURE;
2411 }
2412 else {
2413 if(*pBufSize != pHddCtx->fw->size) {
2414 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2415 "file size", __func__);
2416 release_firmware(pHddCtx->fw);
2417 pHddCtx->fw = NULL;
2418 return VOS_STATUS_E_FAILURE;
2419 }
2420 else {
2421 if(pBuffer) {
2422 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2423 }
2424 release_firmware(pHddCtx->fw);
2425 pHddCtx->fw = NULL;
2426 }
2427 }
2428
2429 EXIT();
2430
2431 return VOS_STATUS_SUCCESS;
2432}
2433
2434/**---------------------------------------------------------------------------
2435
Jeff Johnson295189b2012-06-20 16:38:30 -07002436 \brief hdd_set_mac_address() -
2437
2438 This function sets the user specified mac address using
2439 the command ifconfig wlanX hw ether <mac adress>.
2440
2441 \param - dev - Pointer to the net device.
2442 - addr - Pointer to the sockaddr.
2443 \return - 0 for success, non zero for failure
2444
2445 --------------------------------------------------------------------------*/
2446
2447static int hdd_set_mac_address(struct net_device *dev, void *addr)
2448{
2449 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2450 struct sockaddr *psta_mac_addr = addr;
2451 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2452
2453 ENTER();
2454
2455 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2456
2457#ifdef HDD_SESSIONIZE
2458 // set the MAC address though the STA ID CFG.
2459 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2460 (v_U8_t *)&pAdapter->macAddressCurrent,
2461 sizeof( pAdapter->macAddressCurrent ),
2462 hdd_set_mac_addr_cb, VOS_FALSE );
2463#endif
2464
2465 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2466
2467 EXIT();
2468 return halStatus;
2469}
2470
2471tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2472{
2473 int i;
2474 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2475 {
2476 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2477 break;
2478 }
2479
2480 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2481 return NULL;
2482
2483 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2484 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2485}
2486
2487void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
2488{
2489 int i;
2490 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2491 {
2492 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
2493 {
2494 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
2495 break;
2496 }
2497 }
2498 return;
2499}
2500
2501#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2502 static struct net_device_ops wlan_drv_ops = {
2503 .ndo_open = hdd_open,
2504 .ndo_stop = hdd_stop,
2505 .ndo_uninit = hdd_uninit,
2506 .ndo_start_xmit = hdd_hard_start_xmit,
2507 .ndo_tx_timeout = hdd_tx_timeout,
2508 .ndo_get_stats = hdd_stats,
2509 .ndo_do_ioctl = hdd_ioctl,
2510 .ndo_set_mac_address = hdd_set_mac_address,
2511 .ndo_select_queue = hdd_select_queue,
2512#ifdef WLAN_FEATURE_PACKET_FILTERING
2513#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
2514 .ndo_set_rx_mode = hdd_set_multicast_list,
2515#else
2516 .ndo_set_multicast_list = hdd_set_multicast_list,
2517#endif //LINUX_VERSION_CODE
2518#endif
2519 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002520 static struct net_device_ops wlan_mon_drv_ops = {
2521 .ndo_open = hdd_mon_open,
2522 .ndo_stop = hdd_stop,
2523 .ndo_uninit = hdd_uninit,
2524 .ndo_start_xmit = hdd_mon_hard_start_xmit,
2525 .ndo_tx_timeout = hdd_tx_timeout,
2526 .ndo_get_stats = hdd_stats,
2527 .ndo_do_ioctl = hdd_ioctl,
2528 .ndo_set_mac_address = hdd_set_mac_address,
2529 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002530
2531#endif
2532
2533void hdd_set_station_ops( struct net_device *pWlanDev )
2534{
2535#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2536 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
2537 pWlanDev->netdev_ops = &wlan_drv_ops;
2538#else
2539 pWlanDev->open = hdd_open;
2540 pWlanDev->stop = hdd_stop;
2541 pWlanDev->uninit = hdd_uninit;
2542 pWlanDev->hard_start_xmit = NULL;
2543 pWlanDev->tx_timeout = hdd_tx_timeout;
2544 pWlanDev->get_stats = hdd_stats;
2545 pWlanDev->do_ioctl = hdd_ioctl;
2546 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
2547 pWlanDev->set_mac_address = hdd_set_mac_address;
2548#endif
2549}
2550
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002551static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07002552{
2553 struct net_device *pWlanDev = NULL;
2554 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002555 /*
2556 * cfg80211 initialization and registration....
2557 */
2558 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
2559
Jeff Johnson295189b2012-06-20 16:38:30 -07002560 if(pWlanDev != NULL)
2561 {
2562
2563 //Save the pointer to the net_device in the HDD adapter
2564 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
2565
Jeff Johnson295189b2012-06-20 16:38:30 -07002566 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
2567
2568 pAdapter->dev = pWlanDev;
2569 pAdapter->pHddCtx = pHddCtx;
2570 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
2571
2572 init_completion(&pAdapter->session_open_comp_var);
2573 init_completion(&pAdapter->session_close_comp_var);
2574 init_completion(&pAdapter->disconnect_comp_var);
2575 init_completion(&pAdapter->linkup_event_var);
2576 init_completion(&pAdapter->cancel_rem_on_chan_var);
2577 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07002578#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2579 init_completion(&pAdapter->offchannel_tx_event);
2580#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002581 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002582#ifdef FEATURE_WLAN_TDLS
2583 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002584 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002585 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002586#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002587 init_completion(&pHddCtx->mc_sus_event_var);
2588 init_completion(&pHddCtx->tx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07002589 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07002590
Jeff Johnson295189b2012-06-20 16:38:30 -07002591 pAdapter->isLinkUpSvcNeeded = FALSE;
2592 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
2593 //Init the net_device structure
2594 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2595
2596 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
2597 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
2598 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
2599 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
2600
2601 hdd_set_station_ops( pAdapter->dev );
2602
2603 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002604 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
2605 pAdapter->wdev.wiphy = pHddCtx->wiphy;
2606 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002607 /* set pWlanDev's parent to underlying device */
2608 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
2609 }
2610
2611 return pAdapter;
2612}
2613
2614VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
2615{
2616 struct net_device *pWlanDev = pAdapter->dev;
2617 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2618 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2619 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2620
2621 if( rtnl_lock_held )
2622 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08002623 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07002624 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
2625 {
2626 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
2627 return VOS_STATUS_E_FAILURE;
2628 }
2629 }
2630 if (register_netdevice(pWlanDev))
2631 {
2632 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
2633 return VOS_STATUS_E_FAILURE;
2634 }
2635 }
2636 else
2637 {
2638 if(register_netdev(pWlanDev))
2639 {
2640 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
2641 return VOS_STATUS_E_FAILURE;
2642 }
2643 }
2644 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
2645
2646 return VOS_STATUS_SUCCESS;
2647}
2648
2649eHalStatus hdd_smeCloseSessionCallback(void *pContext)
2650{
2651 if(pContext != NULL)
2652 {
2653 clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags);
2654
2655 /* need to make sure all of our scheduled work has completed.
2656 * This callback is called from MC thread context, so it is safe to
2657 * to call below flush workqueue API from here.
2658 */
2659 flush_scheduled_work();
2660 complete(&((hdd_adapter_t*)pContext)->session_close_comp_var);
2661 }
2662 return eHAL_STATUS_SUCCESS;
2663}
2664
2665VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
2666{
2667 struct net_device *pWlanDev = pAdapter->dev;
2668 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2669 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2670 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2671 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2672 int rc = 0;
2673
2674 INIT_COMPLETION(pAdapter->session_open_comp_var);
2675 //Open a SME session for future operation
2676 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
2677 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
2678 if ( !HAL_STATUS_SUCCESS( halStatus ) )
2679 {
2680 hddLog(VOS_TRACE_LEVEL_FATAL,
2681 "sme_OpenSession() failed with status code %08d [x%08lx]",
2682 halStatus, halStatus );
2683 status = VOS_STATUS_E_FAILURE;
2684 goto error_sme_open;
2685 }
2686
2687 //Block on a completion variable. Can't wait forever though.
2688 rc = wait_for_completion_interruptible_timeout(
2689 &pAdapter->session_open_comp_var,
2690 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2691 if (!rc)
2692 {
2693 hddLog(VOS_TRACE_LEVEL_FATAL,
2694 "Session is not opened within timeout period code %08d", rc );
2695 status = VOS_STATUS_E_FAILURE;
2696 goto error_sme_open;
2697 }
2698
2699 // Register wireless extensions
2700 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
2701 {
2702 hddLog(VOS_TRACE_LEVEL_FATAL,
2703 "hdd_register_wext() failed with status code %08d [x%08lx]",
2704 halStatus, halStatus );
2705 status = VOS_STATUS_E_FAILURE;
2706 goto error_register_wext;
2707 }
2708 //Safe to register the hard_start_xmit function again
2709#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2710 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
2711#else
2712 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
2713#endif
2714
2715 //Set the Connection State to Not Connected
2716 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2717
2718 //Set the default operation channel
2719 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
2720
2721 /* Make the default Auth Type as OPEN*/
2722 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2723
2724 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
2725 {
2726 hddLog(VOS_TRACE_LEVEL_FATAL,
2727 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
2728 status, status );
2729 goto error_init_txrx;
2730 }
2731
2732 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2733
2734 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
2735 {
2736 hddLog(VOS_TRACE_LEVEL_FATAL,
2737 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
2738 status, status );
2739 goto error_wmm_init;
2740 }
2741
2742 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2743
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002744#ifdef FEATURE_WLAN_TDLS
2745 if(0 != wlan_hdd_tdls_init(pAdapter))
2746 {
2747 status = VOS_STATUS_E_FAILURE;
2748 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
2749 goto error_tdls_init;
2750 }
2751 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2752#endif
2753
Jeff Johnson295189b2012-06-20 16:38:30 -07002754 return VOS_STATUS_SUCCESS;
2755
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002756#ifdef FEATURE_WLAN_TDLS
2757error_tdls_init:
2758 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2759 hdd_wmm_adapter_close(pAdapter);
2760#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002761error_wmm_init:
2762 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2763 hdd_deinit_tx_rx(pAdapter);
2764error_init_txrx:
2765 hdd_UnregisterWext(pWlanDev);
2766error_register_wext:
2767 if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
2768 {
2769 INIT_COMPLETION(pAdapter->session_close_comp_var);
2770 if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
2771 pAdapter->sessionId,
2772 hdd_smeCloseSessionCallback, pAdapter ) )
2773 {
2774 //Block on a completion variable. Can't wait forever though.
2775 wait_for_completion_interruptible_timeout(
2776 &pAdapter->session_close_comp_var,
2777 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2778 }
2779}
2780error_sme_open:
2781 return status;
2782}
2783
Jeff Johnson295189b2012-06-20 16:38:30 -07002784void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2785{
2786 hdd_cfg80211_state_t *cfgState;
2787
2788 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
2789
2790 if( NULL != cfgState->buf )
2791 {
2792 int rc;
2793 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
2794 rc = wait_for_completion_interruptible_timeout(
2795 &pAdapter->tx_action_cnf_event,
2796 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2797 if(!rc)
2798 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08002799 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07002800 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
2801 }
2802 }
2803 return;
2804}
Jeff Johnson295189b2012-06-20 16:38:30 -07002805
2806void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2807{
2808 ENTER();
2809 switch ( pAdapter->device_mode )
2810 {
2811 case WLAN_HDD_INFRA_STATION:
2812 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002813 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002814 {
2815 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2816 {
2817 hdd_deinit_tx_rx( pAdapter );
2818 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2819 }
2820
2821 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
2822 {
2823 hdd_wmm_adapter_close( pAdapter );
2824 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2825 }
2826
Jeff Johnson295189b2012-06-20 16:38:30 -07002827 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002828#ifdef FEATURE_WLAN_TDLS
2829 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
2830 {
2831 wlan_hdd_tdls_exit(pAdapter);
2832 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2833 }
2834#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002835
2836 break;
2837 }
2838
2839 case WLAN_HDD_SOFTAP:
2840 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002841 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002842 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002843
2844 hdd_unregister_hostapd(pAdapter);
2845 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07002846 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07002847 break;
2848 }
2849
2850 case WLAN_HDD_MONITOR:
2851 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002852 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07002853 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2854 {
2855 hdd_deinit_tx_rx( pAdapter );
2856 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2857 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002858 if(NULL != pAdapterforTx)
2859 {
2860 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
2861 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002862 break;
2863 }
2864
2865
2866 default:
2867 break;
2868 }
2869
2870 EXIT();
2871}
2872
2873void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
2874{
2875 struct net_device *pWlanDev = pAdapter->dev;
2876
2877 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
2878 if( rtnl_held )
2879 {
2880 unregister_netdevice(pWlanDev);
2881 }
2882 else
2883 {
2884 unregister_netdev(pWlanDev);
2885 }
2886 // note that the pAdapter is no longer valid at this point
2887 // since the memory has been reclaimed
2888 }
2889
2890}
2891
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08002892void hdd_set_pwrparams(hdd_context_t *pHddCtx)
2893{
2894 tSirSetPowerParamsReq powerRequest = { 0 };
2895
2896 powerRequest.uIgnoreDTIM = 1;
2897
2898 if (pHddCtx->cfg_ini->enableModulatedDTIM)
2899 {
2900 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
2901 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2902 }
2903 else
2904 {
2905 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
2906 }
2907
2908 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
2909 *specified during Enter/Exit BMPS when LCD off*/
2910 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2911 NULL, eANI_BOOLEAN_FALSE);
2912 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2913 NULL, eANI_BOOLEAN_FALSE);
2914
2915 /* switch to the DTIM specified in cfg.ini */
2916 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2917 "Switch to DTIM%d", powerRequest.uListenInterval);
2918 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2919
2920}
2921
2922void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
2923{
2924 /*Switch back to DTIM 1*/
2925 tSirSetPowerParamsReq powerRequest = { 0 };
2926
2927 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
2928 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2929
2930 /* Update ignoreDTIM and ListedInterval in CFG with default values */
2931 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2932 NULL, eANI_BOOLEAN_FALSE);
2933 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2934 NULL, eANI_BOOLEAN_FALSE);
2935
2936 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2937 "Switch to DTIM%d",powerRequest.uListenInterval);
2938 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2939
2940}
2941
Jeff Johnson295189b2012-06-20 16:38:30 -07002942VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
2943{
2944 VOS_STATUS status = VOS_STATUS_SUCCESS;
2945
2946 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2947 {
2948 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2949 }
2950
2951 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2952 {
2953 sme_StartAutoBmpsTimer(pHddCtx->hHal);
2954 }
2955
2956 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2957 {
2958 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2959 }
2960
2961 return status;
2962}
2963
2964VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
2965{
2966 hdd_adapter_t *pAdapter = NULL;
2967 eHalStatus halStatus;
2968 VOS_STATUS status = VOS_STATUS_E_INVAL;
2969 v_BOOL_t disableBmps = FALSE;
2970 v_BOOL_t disableImps = FALSE;
2971
2972 switch(session_type)
2973 {
2974 case WLAN_HDD_INFRA_STATION:
2975 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002976 case WLAN_HDD_P2P_CLIENT:
2977 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002978 //Exit BMPS -> Is Sta/P2P Client is already connected
2979 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
2980 if((NULL != pAdapter)&&
2981 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2982 {
2983 disableBmps = TRUE;
2984 }
2985
2986 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
2987 if((NULL != pAdapter)&&
2988 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2989 {
2990 disableBmps = TRUE;
2991 }
2992
2993 //Exit both Bmps and Imps incase of Go/SAP Mode
2994 if((WLAN_HDD_SOFTAP == session_type) ||
2995 (WLAN_HDD_P2P_GO == session_type))
2996 {
2997 disableBmps = TRUE;
2998 disableImps = TRUE;
2999 }
3000
3001 if(TRUE == disableImps)
3002 {
3003 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3004 {
3005 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3006 }
3007 }
3008
3009 if(TRUE == disableBmps)
3010 {
3011 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3012 {
3013 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3014
3015 if(eHAL_STATUS_SUCCESS != halStatus)
3016 {
3017 status = VOS_STATUS_E_FAILURE;
3018 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3019 VOS_ASSERT(0);
3020 return status;
3021 }
3022 }
3023
3024 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3025 {
3026 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3027
3028 if(eHAL_STATUS_SUCCESS != halStatus)
3029 {
3030 status = VOS_STATUS_E_FAILURE;
3031 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3032 VOS_ASSERT(0);
3033 return status;
3034 }
3035 }
3036 }
3037
3038 if((TRUE == disableBmps) ||
3039 (TRUE == disableImps))
3040 {
3041 /* Now, get the chip into Full Power now */
3042 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3043 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3044 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3045
3046 if(halStatus != eHAL_STATUS_SUCCESS)
3047 {
3048 if(halStatus == eHAL_STATUS_PMC_PENDING)
3049 {
3050 //Block on a completion variable. Can't wait forever though
3051 wait_for_completion_interruptible_timeout(
3052 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3053 }
3054 else
3055 {
3056 status = VOS_STATUS_E_FAILURE;
3057 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3058 VOS_ASSERT(0);
3059 return status;
3060 }
3061 }
3062
3063 status = VOS_STATUS_SUCCESS;
3064 }
3065
3066 break;
3067 }
3068 return status;
3069}
3070
3071hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003072 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003073 tANI_U8 rtnl_held )
3074{
3075 hdd_adapter_t *pAdapter = NULL;
3076 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3077 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3078 VOS_STATUS exitbmpsStatus;
3079
3080 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3081
3082 //Disable BMPS incase of Concurrency
3083 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3084
3085 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3086 {
3087 //Fail to Exit BMPS
3088 VOS_ASSERT(0);
3089 return NULL;
3090 }
3091
3092 switch(session_type)
3093 {
3094 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003095 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003096 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003097 {
3098 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3099
3100 if( NULL == pAdapter )
3101 return NULL;
3102
Jeff Johnsone7245742012-09-05 17:12:55 -07003103 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3104 NL80211_IFTYPE_P2P_CLIENT:
3105 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003106
Jeff Johnson295189b2012-06-20 16:38:30 -07003107 pAdapter->device_mode = session_type;
3108
3109 status = hdd_init_station_mode( pAdapter );
3110 if( VOS_STATUS_SUCCESS != status )
3111 goto err_free_netdev;
3112
3113 status = hdd_register_interface( pAdapter, rtnl_held );
3114 if( VOS_STATUS_SUCCESS != status )
3115 {
3116 hdd_deinit_adapter(pHddCtx, pAdapter);
3117 goto err_free_netdev;
3118 }
3119 //Stop the Interface TX queue.
3120 netif_tx_disable(pAdapter->dev);
3121 //netif_tx_disable(pWlanDev);
3122 netif_carrier_off(pAdapter->dev);
3123
3124 break;
3125 }
3126
Jeff Johnson295189b2012-06-20 16:38:30 -07003127 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003128 case WLAN_HDD_SOFTAP:
3129 {
3130 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3131 if( NULL == pAdapter )
3132 return NULL;
3133
Jeff Johnson295189b2012-06-20 16:38:30 -07003134 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3135 NL80211_IFTYPE_AP:
3136 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003137 pAdapter->device_mode = session_type;
3138
3139 status = hdd_init_ap_mode(pAdapter);
3140 if( VOS_STATUS_SUCCESS != status )
3141 goto err_free_netdev;
3142
3143 status = hdd_register_hostapd( pAdapter, rtnl_held );
3144 if( VOS_STATUS_SUCCESS != status )
3145 {
3146 hdd_deinit_adapter(pHddCtx, pAdapter);
3147 goto err_free_netdev;
3148 }
3149
3150 netif_tx_disable(pAdapter->dev);
3151 netif_carrier_off(pAdapter->dev);
3152
3153 hdd_set_conparam( 1 );
3154 break;
3155 }
3156 case WLAN_HDD_MONITOR:
3157 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003158 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3159 if( NULL == pAdapter )
3160 return NULL;
3161
3162 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3163 pAdapter->device_mode = session_type;
3164 status = hdd_register_interface( pAdapter, rtnl_held );
3165#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3166 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3167#else
3168 pAdapter->dev->open = hdd_mon_open;
3169 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3170#endif
3171 hdd_init_tx_rx( pAdapter );
3172 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3173 //Set adapter to be used for data tx. It will use either GO or softap.
3174 pAdapter->sessionCtx.monitor.pAdapterForTx =
3175 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003176 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3177 {
3178 pAdapter->sessionCtx.monitor.pAdapterForTx =
3179 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3180 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003181 /* This workqueue will be used to transmit management packet over
3182 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003183 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3184 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3185 return NULL;
3186 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003187
Jeff Johnson295189b2012-06-20 16:38:30 -07003188 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3189 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003190 }
3191 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003192 case WLAN_HDD_FTM:
3193 {
3194 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3195
3196 if( NULL == pAdapter )
3197 return NULL;
3198 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3199 * message while loading driver in FTM mode. */
3200 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3201 pAdapter->device_mode = session_type;
3202 status = hdd_register_interface( pAdapter, rtnl_held );
3203 }
3204 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003205 default:
3206 {
3207 VOS_ASSERT(0);
3208 return NULL;
3209 }
3210 }
3211
3212
3213 if( VOS_STATUS_SUCCESS == status )
3214 {
3215 //Add it to the hdd's session list.
3216 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3217 if( NULL == pHddAdapterNode )
3218 {
3219 status = VOS_STATUS_E_NOMEM;
3220 }
3221 else
3222 {
3223 pHddAdapterNode->pAdapter = pAdapter;
3224 status = hdd_add_adapter_back ( pHddCtx,
3225 pHddAdapterNode );
3226 }
3227 }
3228
3229 if( VOS_STATUS_SUCCESS != status )
3230 {
3231 if( NULL != pAdapter )
3232 {
3233 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3234 pAdapter = NULL;
3235 }
3236 if( NULL != pHddAdapterNode )
3237 {
3238 vos_mem_free( pHddAdapterNode );
3239 }
3240
3241 goto resume_bmps;
3242 }
3243
3244 if(VOS_STATUS_SUCCESS == status)
3245 {
3246 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3247
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003248 //Initialize the WoWL service
3249 if(!hdd_init_wowl(pAdapter))
3250 {
3251 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3252 goto err_free_netdev;
3253 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003254 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003255 return pAdapter;
3256
3257err_free_netdev:
3258 free_netdev(pAdapter->dev);
3259 wlan_hdd_release_intf_addr( pHddCtx,
3260 pAdapter->macAddressCurrent.bytes );
3261
3262resume_bmps:
3263 //If bmps disabled enable it
3264 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3265 {
3266 hdd_enable_bmps_imps(pHddCtx);
3267 }
3268 return NULL;
3269}
3270
3271VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3272 tANI_U8 rtnl_held )
3273{
3274 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3275 VOS_STATUS status;
3276
3277 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3278 if( VOS_STATUS_SUCCESS != status )
3279 return status;
3280
3281 while ( pCurrent->pAdapter != pAdapter )
3282 {
3283 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3284 if( VOS_STATUS_SUCCESS != status )
3285 break;
3286
3287 pCurrent = pNext;
3288 }
3289 pAdapterNode = pCurrent;
3290 if( VOS_STATUS_SUCCESS == status )
3291 {
3292 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3293 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3294 hdd_remove_adapter( pHddCtx, pAdapterNode );
3295 vos_mem_free( pAdapterNode );
3296
Jeff Johnson295189b2012-06-20 16:38:30 -07003297
3298 /* If there is a single session of STA/P2P client, re-enable BMPS */
3299 if ((!vos_concurrent_sessions_running()) &&
3300 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3301 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3302 {
3303 hdd_enable_bmps_imps(pHddCtx);
3304 }
3305
3306 return VOS_STATUS_SUCCESS;
3307 }
3308
3309 return VOS_STATUS_E_FAILURE;
3310}
3311
3312VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3313{
3314 hdd_adapter_list_node_t *pHddAdapterNode;
3315 VOS_STATUS status;
3316
3317 ENTER();
3318
3319 do
3320 {
3321 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3322 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3323 {
3324 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3325 vos_mem_free( pHddAdapterNode );
3326 }
3327 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3328
3329 EXIT();
3330
3331 return VOS_STATUS_SUCCESS;
3332}
3333
3334void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3335{
3336 v_U8_t addIE[1] = {0};
3337
3338 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3339 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3340 eANI_BOOLEAN_FALSE) )
3341 {
3342 hddLog(LOGE,
3343 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3344 }
3345
3346 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3347 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3348 eANI_BOOLEAN_FALSE) )
3349 {
3350 hddLog(LOGE,
3351 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3352 }
3353
3354 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3355 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3356 eANI_BOOLEAN_FALSE) )
3357 {
3358 hddLog(LOGE,
3359 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3360 }
3361}
3362
3363VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3364{
3365 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3366 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3367 union iwreq_data wrqu;
3368
3369 ENTER();
3370
3371 switch(pAdapter->device_mode)
3372 {
3373 case WLAN_HDD_INFRA_STATION:
3374 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003375 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003376 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3377 {
3378 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3379 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3380 pAdapter->sessionId,
3381 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3382 else
3383 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3384 pAdapter->sessionId,
3385 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3386 //success implies disconnect command got queued up successfully
3387 if(halStatus == eHAL_STATUS_SUCCESS)
3388 {
3389 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3390 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3391 }
3392 memset(&wrqu, '\0', sizeof(wrqu));
3393 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3394 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3395 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3396 }
3397 else
3398 {
3399 hdd_abort_mac_scan(pHddCtx);
3400 }
3401
3402 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3403 {
3404 INIT_COMPLETION(pAdapter->session_close_comp_var);
3405 if (eHAL_STATUS_SUCCESS ==
3406 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3407 hdd_smeCloseSessionCallback, pAdapter))
3408 {
3409 //Block on a completion variable. Can't wait forever though.
3410 wait_for_completion_interruptible_timeout(
3411 &pAdapter->session_close_comp_var,
3412 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3413 }
3414 }
3415
3416 break;
3417
3418 case WLAN_HDD_SOFTAP:
3419 case WLAN_HDD_P2P_GO:
3420 //Any softap specific cleanup here...
3421 mutex_lock(&pHddCtx->sap_lock);
3422 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3423 {
3424 VOS_STATUS status;
3425 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3426
3427 //Stop Bss.
3428 status = WLANSAP_StopBss(pHddCtx->pvosContext);
3429 if (VOS_IS_STATUS_SUCCESS(status))
3430 {
3431 hdd_hostapd_state_t *pHostapdState =
3432 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3433
3434 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
3435
3436 if (!VOS_IS_STATUS_SUCCESS(status))
3437 {
3438 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003439 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003440 }
3441 }
3442 else
3443 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003444 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003445 }
3446 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
3447
3448 if (eHAL_STATUS_FAILURE ==
3449 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
3450 0, NULL, eANI_BOOLEAN_FALSE))
3451 {
3452 hddLog(LOGE,
3453 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003454 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003455 }
3456
3457 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
3458 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
3459 eANI_BOOLEAN_FALSE) )
3460 {
3461 hddLog(LOGE,
3462 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
3463 }
3464
3465 // Reset WNI_CFG_PROBE_RSP Flags
3466 wlan_hdd_reset_prob_rspies(pAdapter);
3467 kfree(pAdapter->sessionCtx.ap.beacon);
3468 pAdapter->sessionCtx.ap.beacon = NULL;
3469 }
3470 mutex_unlock(&pHddCtx->sap_lock);
3471 break;
3472 case WLAN_HDD_MONITOR:
3473 break;
3474 default:
3475 break;
3476 }
3477
3478 EXIT();
3479 return VOS_STATUS_SUCCESS;
3480}
3481
3482VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
3483{
3484 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3485 VOS_STATUS status;
3486 hdd_adapter_t *pAdapter;
3487
3488 ENTER();
3489
3490 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3491
3492 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3493 {
3494 pAdapter = pAdapterNode->pAdapter;
3495 netif_tx_disable(pAdapter->dev);
3496 netif_carrier_off(pAdapter->dev);
3497
3498 hdd_stop_adapter( pHddCtx, pAdapter );
3499
3500 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3501 pAdapterNode = pNext;
3502 }
3503
3504 EXIT();
3505
3506 return VOS_STATUS_SUCCESS;
3507}
3508
3509VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
3510{
3511 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3512 VOS_STATUS status;
3513 hdd_adapter_t *pAdapter;
3514
3515 ENTER();
3516
3517 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3518
3519 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3520 {
3521 pAdapter = pAdapterNode->pAdapter;
3522 netif_tx_disable(pAdapter->dev);
3523 netif_carrier_off(pAdapter->dev);
3524
3525 //Record whether STA is associated
3526 pAdapter->sessionCtx.station.bSendDisconnect =
3527 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
3528 VOS_TRUE : VOS_FALSE;
3529
3530 hdd_deinit_tx_rx(pAdapter);
3531 hdd_wmm_adapter_close(pAdapter);
3532
3533 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3534 pAdapterNode = pNext;
3535 }
3536
3537 EXIT();
3538
3539 return VOS_STATUS_SUCCESS;
3540}
3541
3542VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
3543{
3544 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3545 VOS_STATUS status;
3546 hdd_adapter_t *pAdapter;
3547 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
3548
3549 ENTER();
3550
3551 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3552
3553 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3554 {
3555 pAdapter = pAdapterNode->pAdapter;
3556
3557 switch(pAdapter->device_mode)
3558 {
3559 case WLAN_HDD_INFRA_STATION:
3560 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003561 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003562 hdd_init_station_mode(pAdapter);
3563 /* Open the gates for HDD to receive Wext commands */
3564 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003565 pHddCtx->scan_info.mScanPending = FALSE;
3566 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003567
3568 //Trigger the initial scan
3569 hdd_wlan_initial_scan(pAdapter);
3570
3571 //Indicate disconnect event to supplicant if associated previously
3572 if(pAdapter->sessionCtx.station.bSendDisconnect)
3573 {
3574 union iwreq_data wrqu;
3575 memset(&wrqu, '\0', sizeof(wrqu));
3576 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3577 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3578 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3579 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
3580
Jeff Johnson295189b2012-06-20 16:38:30 -07003581 /* indicate disconnected event to nl80211 */
3582 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
3583 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003584 }
3585 break;
3586
3587 case WLAN_HDD_SOFTAP:
3588 /* softAP can handle SSR */
3589 break;
3590
3591 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003592 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
3593 __func__);
3594 /* event supplicant to restart */
3595 cfg80211_del_sta(pAdapter->dev,
3596 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003597 break;
3598
3599 case WLAN_HDD_MONITOR:
3600 /* monitor interface start */
3601 break;
3602 default:
3603 break;
3604 }
3605
3606 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3607 pAdapterNode = pNext;
3608 }
3609
3610 EXIT();
3611
3612 return VOS_STATUS_SUCCESS;
3613}
3614
3615VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
3616{
3617 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3618 hdd_adapter_t *pAdapter;
3619 VOS_STATUS status;
3620 v_U32_t roamId;
3621
3622 ENTER();
3623
3624 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3625
3626 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3627 {
3628 pAdapter = pAdapterNode->pAdapter;
3629
3630 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3631 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
3632 {
3633 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3634 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3635
3636 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3637 init_completion(&pAdapter->disconnect_comp_var);
3638 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
3639 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3640
3641 wait_for_completion_interruptible_timeout(
3642 &pAdapter->disconnect_comp_var,
3643 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3644
3645 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
3646 pHddCtx->isAmpAllowed = VOS_FALSE;
3647 sme_RoamConnect(pHddCtx->hHal,
3648 pAdapter->sessionId, &(pWextState->roamProfile),
3649 &roamId);
3650 }
3651
3652 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3653 pAdapterNode = pNext;
3654 }
3655
3656 EXIT();
3657
3658 return VOS_STATUS_SUCCESS;
3659}
3660
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07003661void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
3662{
3663 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3664 VOS_STATUS status;
3665 hdd_adapter_t *pAdapter;
3666 hdd_station_ctx_t *pHddStaCtx;
3667 hdd_ap_ctx_t *pHddApCtx;
3668 hdd_hostapd_state_t * pHostapdState;
3669 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
3670 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
3671 const char *p2pMode = "DEV";
3672 const char *ccMode = "Standalone";
3673 int n;
3674
3675 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3676 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3677 {
3678 pAdapter = pAdapterNode->pAdapter;
3679 switch (pAdapter->device_mode) {
3680 case WLAN_HDD_INFRA_STATION:
3681 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3682 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3683 staChannel = pHddStaCtx->conn_info.operationChannel;
3684 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
3685 }
3686 break;
3687 case WLAN_HDD_P2P_CLIENT:
3688 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3689 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3690 p2pChannel = pHddStaCtx->conn_info.operationChannel;
3691 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
3692 p2pMode = "CLI";
3693 }
3694 break;
3695 case WLAN_HDD_P2P_GO:
3696 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3697 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3698 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3699 p2pChannel = pHddApCtx->operatingChannel;
3700 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
3701 }
3702 p2pMode = "GO";
3703 break;
3704 case WLAN_HDD_SOFTAP:
3705 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3706 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3707 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3708 apChannel = pHddApCtx->operatingChannel;
3709 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
3710 }
3711 break;
3712 default:
3713 break;
3714 }
3715 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3716 pAdapterNode = pNext;
3717 }
3718 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
3719 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
3720 }
3721 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
3722 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
3723 if (p2pChannel > 0) {
3724 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
3725 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
3726 }
3727 if (apChannel > 0) {
3728 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
3729 apChannel, MAC_ADDR_ARRAY(apBssid));
3730 }
3731
3732 if (p2pChannel > 0 && apChannel > 0) {
3733 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
3734 }
3735}
3736
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003737bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07003738{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003739 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07003740}
3741
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003742/* Once SSR is disabled then it cannot be set. */
3743void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07003744{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003745 if (HDD_SSR_DISABLED == isSsrRequired)
3746 return;
3747
Jeff Johnson295189b2012-06-20 16:38:30 -07003748 isSsrRequired = value;
3749}
3750
3751VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
3752 hdd_adapter_list_node_t** ppAdapterNode)
3753{
3754 VOS_STATUS status;
3755 spin_lock(&pHddCtx->hddAdapters.lock);
3756 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
3757 (hdd_list_node_t**) ppAdapterNode );
3758 spin_unlock(&pHddCtx->hddAdapters.lock);
3759 return status;
3760}
3761
3762VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
3763 hdd_adapter_list_node_t* pAdapterNode,
3764 hdd_adapter_list_node_t** pNextAdapterNode)
3765{
3766 VOS_STATUS status;
3767 spin_lock(&pHddCtx->hddAdapters.lock);
3768 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
3769 (hdd_list_node_t*) pAdapterNode,
3770 (hdd_list_node_t**)pNextAdapterNode );
3771
3772 spin_unlock(&pHddCtx->hddAdapters.lock);
3773 return status;
3774}
3775
3776VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
3777 hdd_adapter_list_node_t* pAdapterNode)
3778{
3779 VOS_STATUS status;
3780 spin_lock(&pHddCtx->hddAdapters.lock);
3781 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
3782 &pAdapterNode->node );
3783 spin_unlock(&pHddCtx->hddAdapters.lock);
3784 return status;
3785}
3786
3787VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
3788 hdd_adapter_list_node_t** ppAdapterNode)
3789{
3790 VOS_STATUS status;
3791 spin_lock(&pHddCtx->hddAdapters.lock);
3792 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
3793 (hdd_list_node_t**) ppAdapterNode );
3794 spin_unlock(&pHddCtx->hddAdapters.lock);
3795 return status;
3796}
3797
3798VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
3799 hdd_adapter_list_node_t* pAdapterNode)
3800{
3801 VOS_STATUS status;
3802 spin_lock(&pHddCtx->hddAdapters.lock);
3803 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
3804 (hdd_list_node_t*) pAdapterNode );
3805 spin_unlock(&pHddCtx->hddAdapters.lock);
3806 return status;
3807}
3808
3809VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
3810 hdd_adapter_list_node_t* pAdapterNode)
3811{
3812 VOS_STATUS status;
3813 spin_lock(&pHddCtx->hddAdapters.lock);
3814 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
3815 (hdd_list_node_t*) pAdapterNode );
3816 spin_unlock(&pHddCtx->hddAdapters.lock);
3817 return status;
3818}
3819
3820hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
3821 tSirMacAddr macAddr )
3822{
3823 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3824 hdd_adapter_t *pAdapter;
3825 VOS_STATUS status;
3826
3827 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3828
3829 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3830 {
3831 pAdapter = pAdapterNode->pAdapter;
3832
3833 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
3834 macAddr, sizeof(tSirMacAddr) ) )
3835 {
3836 return pAdapter;
3837 }
3838 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3839 pAdapterNode = pNext;
3840 }
3841
3842 return NULL;
3843
3844}
3845
3846hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
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 && !strncmp( pAdapter->dev->name, (const char *)name,
3859 IFNAMSIZ ) )
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( hdd_context_t *pHddCtx, device_mode_t mode )
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 && (mode == pAdapter->device_mode) )
3884 {
3885 return pAdapter;
3886 }
3887 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3888 pAdapterNode = pNext;
3889 }
3890
3891 return NULL;
3892
3893}
3894
3895//Remove this function later
3896hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
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 && WLAN_HDD_MONITOR == pAdapter->device_mode )
3909 {
3910 return pAdapter;
3911 }
3912
3913 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3914 pAdapterNode = pNext;
3915 }
3916
3917 return NULL;
3918
3919}
3920
Jeff Johnson295189b2012-06-20 16:38:30 -07003921/**---------------------------------------------------------------------------
3922
3923 \brief hdd_set_monitor_tx_adapter() -
3924
3925 This API initializes the adapter to be used while transmitting on monitor
3926 adapter.
3927
3928 \param - pHddCtx - Pointer to the HDD context.
3929 pAdapter - Adapter that will used for TX. This can be NULL.
3930 \return - None.
3931 --------------------------------------------------------------------------*/
3932void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3933{
3934 hdd_adapter_t *pMonAdapter;
3935
3936 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
3937
3938 if( NULL != pMonAdapter )
3939 {
3940 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
3941 }
3942}
Jeff Johnson295189b2012-06-20 16:38:30 -07003943/**---------------------------------------------------------------------------
3944
3945 \brief hdd_select_queue() -
3946
3947 This API returns the operating channel of the requested device mode
3948
3949 \param - pHddCtx - Pointer to the HDD context.
3950 - mode - Device mode for which operating channel is required
3951 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
3952 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
3953 \return - channel number. "0" id the requested device is not found OR it is not connected.
3954 --------------------------------------------------------------------------*/
3955v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
3956{
3957 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3958 VOS_STATUS status;
3959 hdd_adapter_t *pAdapter;
3960 v_U8_t operatingChannel = 0;
3961
3962 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3963
3964 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3965 {
3966 pAdapter = pAdapterNode->pAdapter;
3967
3968 if( mode == pAdapter->device_mode )
3969 {
3970 switch(pAdapter->device_mode)
3971 {
3972 case WLAN_HDD_INFRA_STATION:
3973 case WLAN_HDD_P2P_CLIENT:
3974 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3975 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
3976 break;
3977 case WLAN_HDD_SOFTAP:
3978 case WLAN_HDD_P2P_GO:
3979 /*softap connection info */
3980 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3981 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
3982 break;
3983 default:
3984 break;
3985 }
3986
3987 break; //Found the device of interest. break the loop
3988 }
3989
3990 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3991 pAdapterNode = pNext;
3992 }
3993 return operatingChannel;
3994}
3995
3996#ifdef WLAN_FEATURE_PACKET_FILTERING
3997/**---------------------------------------------------------------------------
3998
3999 \brief hdd_set_multicast_list() -
4000
4001 This used to set the multicast address list.
4002
4003 \param - dev - Pointer to the WLAN device.
4004 - skb - Pointer to OS packet (sk_buff).
4005 \return - success/fail
4006
4007 --------------------------------------------------------------------------*/
4008static void hdd_set_multicast_list(struct net_device *dev)
4009{
4010 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004011 int mc_count;
4012 int i = 0;
4013 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304014
4015 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004016 {
4017 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304018 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004019 return;
4020 }
4021
4022 if (dev->flags & IFF_ALLMULTI)
4023 {
4024 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004025 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304026 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004027 }
4028 else
4029 {
4030 mc_count = netdev_mc_count(dev);
4031 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004032 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004033 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4034 {
4035 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004036 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304037 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004038 return;
4039 }
4040
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304041 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004042
4043 netdev_for_each_mc_addr(ha, dev) {
4044 if (i == mc_count)
4045 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304046 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4047 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4048 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004049 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304050 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004051 i++;
4052 }
4053 }
4054 return;
4055}
4056#endif
4057
4058/**---------------------------------------------------------------------------
4059
4060 \brief hdd_select_queue() -
4061
4062 This function is registered with the Linux OS for network
4063 core to decide which queue to use first.
4064
4065 \param - dev - Pointer to the WLAN device.
4066 - skb - Pointer to OS packet (sk_buff).
4067 \return - ac, Queue Index/access category corresponding to UP in IP header
4068
4069 --------------------------------------------------------------------------*/
4070v_U16_t hdd_select_queue(struct net_device *dev,
4071 struct sk_buff *skb)
4072{
4073 return hdd_wmm_select_queue(dev, skb);
4074}
4075
4076
4077/**---------------------------------------------------------------------------
4078
4079 \brief hdd_wlan_initial_scan() -
4080
4081 This function triggers the initial scan
4082
4083 \param - pAdapter - Pointer to the HDD adapter.
4084
4085 --------------------------------------------------------------------------*/
4086void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4087{
4088 tCsrScanRequest scanReq;
4089 tCsrChannelInfo channelInfo;
4090 eHalStatus halStatus;
4091 unsigned long scanId;
4092 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4093
4094 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4095 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4096 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4097
4098 if(sme_Is11dSupported(pHddCtx->hHal))
4099 {
4100 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4101 if ( HAL_STATUS_SUCCESS( halStatus ) )
4102 {
4103 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4104 if( !scanReq.ChannelInfo.ChannelList )
4105 {
4106 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4107 vos_mem_free(channelInfo.ChannelList);
4108 return;
4109 }
4110 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4111 channelInfo.numOfChannels);
4112 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4113 vos_mem_free(channelInfo.ChannelList);
4114 }
4115
4116 scanReq.scanType = eSIR_PASSIVE_SCAN;
4117 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4118 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4119 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4120 }
4121 else
4122 {
4123 scanReq.scanType = eSIR_ACTIVE_SCAN;
4124 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4125 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4126 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4127 }
4128
4129 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4130 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4131 {
4132 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4133 __func__, halStatus );
4134 }
4135
4136 if(sme_Is11dSupported(pHddCtx->hHal))
4137 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4138}
4139
4140struct fullPowerContext
4141{
4142 struct completion completion;
4143 unsigned int magic;
4144};
4145#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4146
4147/**---------------------------------------------------------------------------
4148
4149 \brief hdd_full_power_callback() - HDD full power callback function
4150
4151 This is the function invoked by SME to inform the result of a full power
4152 request issued by HDD
4153
4154 \param - callbackcontext - Pointer to cookie
4155 \param - status - result of request
4156
4157 \return - None
4158
4159 --------------------------------------------------------------------------*/
4160static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4161{
4162 struct fullPowerContext *pContext = callbackContext;
4163
4164 hddLog(VOS_TRACE_LEVEL_INFO,
4165 "%s: context = %p, status = %d", pContext, status);
4166
4167 if (NULL == callbackContext)
4168 {
4169 hddLog(VOS_TRACE_LEVEL_ERROR,
4170 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004171 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004172 return;
4173 }
4174
4175 /* there is a race condition that exists between this callback function
4176 and the caller since the caller could time out either before or
4177 while this code is executing. we'll assume the timeout hasn't
4178 occurred, but we'll verify that right before we save our work */
4179
4180 if (POWER_CONTEXT_MAGIC != pContext->magic)
4181 {
4182 /* the caller presumably timed out so there is nothing we can do */
4183 hddLog(VOS_TRACE_LEVEL_WARN,
4184 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004185 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004186 return;
4187 }
4188
4189 /* the race is on. caller could have timed out immediately after
4190 we verified the magic, but if so, caller will wait a short time
4191 for us to notify the caller, so the context will stay valid */
4192 complete(&pContext->completion);
4193}
4194
4195/**---------------------------------------------------------------------------
4196
4197 \brief hdd_wlan_exit() - HDD WLAN exit function
4198
4199 This is the driver exit point (invoked during rmmod)
4200
4201 \param - pHddCtx - Pointer to the HDD Context
4202
4203 \return - None
4204
4205 --------------------------------------------------------------------------*/
4206void hdd_wlan_exit(hdd_context_t *pHddCtx)
4207{
4208 eHalStatus halStatus;
4209 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4210 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304211 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004212 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004213 struct fullPowerContext powerContext;
4214 long lrc;
4215
4216 ENTER();
4217
Jeff Johnson88ba7742013-02-27 14:36:02 -08004218 if (VOS_FTM_MODE != hdd_get_conparam())
4219 {
4220 // Unloading, restart logic is no more required.
4221 wlan_hdd_restart_deinit(pHddCtx);
4222 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004223
Jeff Johnson295189b2012-06-20 16:38:30 -07004224 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004225 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004226 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004227 {
4228 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4229 WLAN_HDD_INFRA_STATION);
4230 if (pAdapter == NULL)
4231 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4232
4233 if (pAdapter != NULL)
4234 {
4235 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4236 hdd_UnregisterWext(pAdapter->dev);
4237 }
4238 }
4239 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004240
Jeff Johnson295189b2012-06-20 16:38:30 -07004241 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004242 {
4243 wlan_hdd_ftm_close(pHddCtx);
4244 goto free_hdd_ctx;
4245 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004246 //Stop the Interface TX queue.
4247 //netif_tx_disable(pWlanDev);
4248 //netif_carrier_off(pWlanDev);
4249
Jeff Johnson295189b2012-06-20 16:38:30 -07004250 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4251 {
4252 pAdapter = hdd_get_adapter(pHddCtx,
4253 WLAN_HDD_SOFTAP);
4254 }
4255 else
4256 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004257 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004258 {
4259 pAdapter = hdd_get_adapter(pHddCtx,
4260 WLAN_HDD_INFRA_STATION);
4261 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004262 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004263 /* DeRegister with platform driver as client for Suspend/Resume */
4264 vosStatus = hddDeregisterPmOps(pHddCtx);
4265 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4266 {
4267 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4268 VOS_ASSERT(0);
4269 }
4270
4271 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4272 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4273 {
4274 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4275 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004276
4277 // Cancel any outstanding scan requests. We are about to close all
4278 // of our adapters, but an adapter structure is what SME passes back
4279 // to our callback function. Hence if there are any outstanding scan
4280 // requests then there is a race condition between when the adapter
4281 // is closed and when the callback is invoked. We try to resolve that
4282 // race condition here by canceling any outstanding scans before we
4283 // close the adapters.
4284 // Note that the scans may be cancelled in an asynchronous manner, so
4285 // ideally there needs to be some kind of synchronization. Rather than
4286 // introduce a new synchronization here, we will utilize the fact that
4287 // we are about to Request Full Power, and since that is synchronized,
4288 // the expectation is that by the time Request Full Power has completed,
4289 // all scans will be cancelled.
4290 hdd_abort_mac_scan( pHddCtx );
4291
4292 //Disable IMPS/BMPS as we do not want the device to enter any power
4293 //save mode during shutdown
4294 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4295 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4296 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4297
4298 //Ensure that device is in full power as we will touch H/W during vos_Stop
4299 init_completion(&powerContext.completion);
4300 powerContext.magic = POWER_CONTEXT_MAGIC;
4301
4302 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4303 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4304
4305 if (eHAL_STATUS_SUCCESS != halStatus)
4306 {
4307 if (eHAL_STATUS_PMC_PENDING == halStatus)
4308 {
4309 /* request was sent -- wait for the response */
4310 lrc = wait_for_completion_interruptible_timeout(
4311 &powerContext.completion,
4312 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4313 /* either we have a response or we timed out
4314 either way, first invalidate our magic */
4315 powerContext.magic = 0;
4316 if (lrc <= 0)
4317 {
4318 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004319 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004320 /* there is a race condition such that the callback
4321 function could be executing at the same time we are. of
4322 primary concern is if the callback function had already
4323 verified the "magic" but hasn't yet set the completion
4324 variable. Since the completion variable is on our
4325 stack, we'll delay just a bit to make sure the data is
4326 still valid if that is the case */
4327 msleep(50);
4328 }
4329 }
4330 else
4331 {
4332 hddLog(VOS_TRACE_LEVEL_ERROR,
4333 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004334 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004335 VOS_ASSERT(0);
4336 /* continue -- need to clean up as much as possible */
4337 }
4338 }
4339
4340 // Unregister the Net Device Notifier
4341 unregister_netdevice_notifier(&hdd_netdev_notifier);
4342
Jeff Johnson295189b2012-06-20 16:38:30 -07004343 hdd_stop_all_adapters( pHddCtx );
4344
Jeff Johnson295189b2012-06-20 16:38:30 -07004345#ifdef WLAN_BTAMP_FEATURE
4346 vosStatus = WLANBAP_Stop(pVosContext);
4347 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4348 {
4349 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4350 "%s: Failed to stop BAP",__func__);
4351 }
4352#endif //WLAN_BTAMP_FEATURE
4353
4354 //Stop all the modules
4355 vosStatus = vos_stop( pVosContext );
4356 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4357 {
4358 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4359 "%s: Failed to stop VOSS",__func__);
4360 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4361 }
4362
Jeff Johnson295189b2012-06-20 16:38:30 -07004363 //Assert Deep sleep signal now to put Libra HW in lowest power state
4364 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4365 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4366
4367 //Vote off any PMIC voltage supplies
4368 vos_chipPowerDown(NULL, NULL, NULL);
4369
4370 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4371
4372 //Clean up HDD Nlink Service
4373 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
4374 nl_srv_exit();
4375
4376 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004377 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004378
4379 //Close the scheduler before calling vos_close to make sure no thread is
4380 // scheduled after the each module close is called i.e after all the data
4381 // structures are freed.
4382 vosStatus = vos_sched_close( pVosContext );
4383 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4384 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4385 "%s: Failed to close VOSS Scheduler",__func__);
4386 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4387 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004388#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004389#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4390 /* Destroy the wake lock */
4391 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4392#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004393 /* Destroy the wake lock */
4394 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004395#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004396
4397 //Close VOSS
4398 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4399 vos_close(pVosContext);
4400
Jeff Johnson295189b2012-06-20 16:38:30 -07004401 //Close Watchdog
4402 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4403 vos_watchdog_close(pVosContext);
4404
4405 /* Cancel the vote for XO Core ON.
4406 * This is done here to ensure there is no race condition since MC, TX and WD threads have
4407 * exited at this point
4408 */
4409 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
4410 " when WLAN is turned OFF\n");
4411 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4412 {
4413 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
4414 " Not returning failure."
4415 " Power consumed will be high\n");
4416 }
4417
4418 hdd_close_all_adapters( pHddCtx );
4419
4420
4421 //Free up dynamically allocated members inside HDD Adapter
4422 kfree(pHddCtx->cfg_ini);
4423 pHddCtx->cfg_ini= NULL;
4424
4425 /* free the power on lock from platform driver */
4426 if (free_riva_power_on_lock("wlan"))
4427 {
4428 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
4429 __func__);
4430 }
4431
Jeff Johnson88ba7742013-02-27 14:36:02 -08004432free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08004433 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004434 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004435 if (hdd_is_ssr_required())
4436 {
4437 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07004438 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07004439 msleep(5000);
4440 }
4441 hdd_set_ssr_required (VOS_FALSE);
4442}
4443
4444
4445/**---------------------------------------------------------------------------
4446
4447 \brief hdd_update_config_from_nv() - Function to update the contents of
4448 the running configuration with parameters taken from NV storage
4449
4450 \param - pHddCtx - Pointer to the HDD global context
4451
4452 \return - VOS_STATUS_SUCCESS if successful
4453
4454 --------------------------------------------------------------------------*/
4455static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
4456{
Jeff Johnson295189b2012-06-20 16:38:30 -07004457 v_BOOL_t itemIsValid = VOS_FALSE;
4458 VOS_STATUS status;
4459 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
4460 v_U8_t macLoop;
4461
4462 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
4463 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
4464 if(status != VOS_STATUS_SUCCESS)
4465 {
4466 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
4467 return VOS_STATUS_E_FAILURE;
4468 }
4469
4470 if (itemIsValid == VOS_TRUE)
4471 {
4472 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
4473 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
4474 VOS_MAX_CONCURRENCY_PERSONA);
4475 if(status != VOS_STATUS_SUCCESS)
4476 {
4477 /* Get MAC from NV fail, not update CFG info
4478 * INI MAC value will be used for MAC setting */
4479 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
4480 return VOS_STATUS_E_FAILURE;
4481 }
4482
4483 /* If first MAC is not valid, treat all others are not valid
4484 * Then all MACs will be got from ini file */
4485 if(vos_is_macaddr_zero(&macFromNV[0]))
4486 {
4487 /* MAC address in NV file is not configured yet */
4488 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
4489 return VOS_STATUS_E_INVAL;
4490 }
4491
4492 /* Get MAC address from NV, update CFG info */
4493 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
4494 {
4495 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
4496 {
4497 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
4498 /* This MAC is not valid, skip it
4499 * This MAC will be got from ini file */
4500 }
4501 else
4502 {
4503 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
4504 (v_U8_t *)&macFromNV[macLoop].bytes[0],
4505 VOS_MAC_ADDR_SIZE);
4506 }
4507 }
4508 }
4509 else
4510 {
4511 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
4512 return VOS_STATUS_E_FAILURE;
4513 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004514
Jeff Johnson295189b2012-06-20 16:38:30 -07004515
4516 return VOS_STATUS_SUCCESS;
4517}
4518
4519/**---------------------------------------------------------------------------
4520
4521 \brief hdd_post_voss_start_config() - HDD post voss start config helper
4522
4523 \param - pAdapter - Pointer to the HDD
4524
4525 \return - None
4526
4527 --------------------------------------------------------------------------*/
4528VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
4529{
4530 eHalStatus halStatus;
4531 v_U32_t listenInterval;
4532
Jeff Johnson295189b2012-06-20 16:38:30 -07004533
4534 // Send ready indication to the HDD. This will kick off the MAC
4535 // into a 'running' state and should kick off an initial scan.
4536 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
4537 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4538 {
4539 hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
4540 "code %08d [x%08x]",__func__, halStatus, halStatus );
4541 return VOS_STATUS_E_FAILURE;
4542 }
4543
4544 // Set default LI into HDD context,
4545 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
4546 // And RIVA will crash
4547 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
4548 pHddCtx->hdd_actual_LI_value = listenInterval;
4549
4550 return VOS_STATUS_SUCCESS;
4551}
4552
Jeff Johnson295189b2012-06-20 16:38:30 -07004553/* wake lock APIs for HDD */
4554void hdd_prevent_suspend(void)
4555{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004556#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004557 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004558#else
4559 wcnss_prevent_suspend();
4560#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004561}
4562
4563void hdd_allow_suspend(void)
4564{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004565#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004566 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004567#else
4568 wcnss_allow_suspend();
4569#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004570}
4571
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004572void hdd_allow_suspend_timeout(v_U32_t timeout)
4573{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004574#ifdef WLAN_OPEN_SOURCE
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004575 wake_lock_timeout(&wlan_wake_lock, timeout);
4576#else
4577 /* Do nothing as there is no API in wcnss for timeout*/
4578#endif
4579}
4580
Jeff Johnson295189b2012-06-20 16:38:30 -07004581/**---------------------------------------------------------------------------
4582
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004583 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
4584 information between Host and Riva
4585
4586 This function gets reported version of FW
4587 It also finds the version of Riva headers used to compile the host
4588 It compares the above two and prints a warning if they are different
4589 It gets the SW and HW version string
4590 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
4591 indicating the features they support through a bitmap
4592
4593 \param - pHddCtx - Pointer to HDD context
4594
4595 \return - void
4596
4597 --------------------------------------------------------------------------*/
4598
4599void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
4600{
4601
4602 tSirVersionType versionCompiled;
4603 tSirVersionType versionReported;
4604 tSirVersionString versionString;
4605 tANI_U8 fwFeatCapsMsgSupported = 0;
4606 VOS_STATUS vstatus;
4607
4608 /* retrieve and display WCNSS version information */
4609 do {
4610
4611 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
4612 &versionCompiled);
4613 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4614 {
4615 hddLog(VOS_TRACE_LEVEL_FATAL,
4616 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004617 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004618 break;
4619 }
4620
4621 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
4622 &versionReported);
4623 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4624 {
4625 hddLog(VOS_TRACE_LEVEL_FATAL,
4626 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004627 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004628 break;
4629 }
4630
4631 if ((versionCompiled.major != versionReported.major) ||
4632 (versionCompiled.minor != versionReported.minor) ||
4633 (versionCompiled.version != versionReported.version) ||
4634 (versionCompiled.revision != versionReported.revision))
4635 {
4636 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4637 "Host expected %u.%u.%u.%u\n",
4638 WLAN_MODULE_NAME,
4639 (int)versionReported.major,
4640 (int)versionReported.minor,
4641 (int)versionReported.version,
4642 (int)versionReported.revision,
4643 (int)versionCompiled.major,
4644 (int)versionCompiled.minor,
4645 (int)versionCompiled.version,
4646 (int)versionCompiled.revision);
4647 }
4648 else
4649 {
4650 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4651 WLAN_MODULE_NAME,
4652 (int)versionReported.major,
4653 (int)versionReported.minor,
4654 (int)versionReported.version,
4655 (int)versionReported.revision);
4656 }
4657
4658 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
4659 versionString,
4660 sizeof(versionString));
4661 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4662 {
4663 hddLog(VOS_TRACE_LEVEL_FATAL,
4664 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004665 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004666 break;
4667 }
4668
4669 pr_info("%s: WCNSS software version %s\n",
4670 WLAN_MODULE_NAME, versionString);
4671
4672 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
4673 versionString,
4674 sizeof(versionString));
4675 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4676 {
4677 hddLog(VOS_TRACE_LEVEL_FATAL,
4678 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004679 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004680 break;
4681 }
4682
4683 pr_info("%s: WCNSS hardware version %s\n",
4684 WLAN_MODULE_NAME, versionString);
4685
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004686 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
4687 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004688 send the message only if it the riva is 1.1
4689 minor numbers for different riva branches:
4690 0 -> (1.0)Mainline Build
4691 1 -> (1.1)Mainline Build
4692 2->(1.04) Stability Build
4693 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004694 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004695 ((versionReported.minor>=1) && (versionReported.version>=1)))
4696 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
4697 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004698
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004699 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08004700 {
4701#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4702 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
4703 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
4704#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004705 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08004706 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004707
4708 } while (0);
4709
4710}
4711
4712/**---------------------------------------------------------------------------
4713
Jeff Johnson295189b2012-06-20 16:38:30 -07004714 \brief hdd_wlan_startup() - HDD init function
4715
4716 This is the driver startup code executed once a WLAN device has been detected
4717
4718 \param - dev - Pointer to the underlying device
4719
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004720 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07004721
4722 --------------------------------------------------------------------------*/
4723
4724int hdd_wlan_startup(struct device *dev )
4725{
4726 VOS_STATUS status;
4727 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004728 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004729 hdd_context_t *pHddCtx = NULL;
4730 v_CONTEXT_t pVosContext= NULL;
4731#ifdef WLAN_BTAMP_FEATURE
4732 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
4733 WLANBAP_ConfigType btAmpConfig;
4734 hdd_config_t *pConfig;
4735#endif
4736 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07004737 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004738
4739 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07004740 /*
4741 * cfg80211: wiphy allocation
4742 */
4743 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
4744
4745 if(wiphy == NULL)
4746 {
4747 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004748 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004749 }
4750
4751 pHddCtx = wiphy_priv(wiphy);
4752
Jeff Johnson295189b2012-06-20 16:38:30 -07004753 //Initialize the adapter context to zeros.
4754 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
4755
Jeff Johnson295189b2012-06-20 16:38:30 -07004756 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004757 hdd_prevent_suspend();
4758 pHddCtx->isLoadUnloadInProgress = TRUE;
4759
4760 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4761
4762 /*Get vos context here bcoz vos_open requires it*/
4763 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4764
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08004765 if(pVosContext == NULL)
4766 {
4767 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
4768 goto err_free_hdd_context;
4769 }
4770
Jeff Johnson295189b2012-06-20 16:38:30 -07004771 //Save the Global VOSS context in adapter context for future.
4772 pHddCtx->pvosContext = pVosContext;
4773
4774 //Save the adapter context in global context for future.
4775 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
4776
Jeff Johnson295189b2012-06-20 16:38:30 -07004777 pHddCtx->parent_dev = dev;
4778
4779 init_completion(&pHddCtx->full_pwr_comp_var);
4780 init_completion(&pHddCtx->standby_comp_var);
4781 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004782 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004783 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004784
4785 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
4786
4787 // Load all config first as TL config is needed during vos_open
4788 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
4789 if(pHddCtx->cfg_ini == NULL)
4790 {
4791 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
4792 goto err_free_hdd_context;
4793 }
4794
4795 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
4796
4797 // Read and parse the qcom_cfg.ini file
4798 status = hdd_parse_config_ini( pHddCtx );
4799 if ( VOS_STATUS_SUCCESS != status )
4800 {
4801 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
4802 __func__, WLAN_INI_FILE);
4803 goto err_config;
4804 }
4805
Jeff Johnson295189b2012-06-20 16:38:30 -07004806 /*
4807 * cfg80211: Initialization and registration ...
4808 */
4809 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
4810 {
4811 hddLog(VOS_TRACE_LEVEL_FATAL,
4812 "%s: wlan_hdd_cfg80211_register return failure", __func__);
4813 goto err_wiphy_reg;
4814 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004815
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004816 // Update VOS trace levels based upon the cfg.ini
4817 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
4818 pHddCtx->cfg_ini->vosTraceEnableBAP);
4819 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
4820 pHddCtx->cfg_ini->vosTraceEnableTL);
4821 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
4822 pHddCtx->cfg_ini->vosTraceEnableWDI);
4823 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
4824 pHddCtx->cfg_ini->vosTraceEnableHDD);
4825 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
4826 pHddCtx->cfg_ini->vosTraceEnableSME);
4827 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
4828 pHddCtx->cfg_ini->vosTraceEnablePE);
4829 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
4830 pHddCtx->cfg_ini->vosTraceEnableWDA);
4831 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
4832 pHddCtx->cfg_ini->vosTraceEnableSYS);
4833 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
4834 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004835 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
4836 pHddCtx->cfg_ini->vosTraceEnableSAP);
4837 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
4838 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004839
Jeff Johnson295189b2012-06-20 16:38:30 -07004840 // Update WDI trace levels based upon the cfg.ini
4841 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
4842 pHddCtx->cfg_ini->wdiTraceEnableDAL);
4843 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
4844 pHddCtx->cfg_ini->wdiTraceEnableCTL);
4845 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
4846 pHddCtx->cfg_ini->wdiTraceEnableDAT);
4847 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
4848 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004849
Jeff Johnson88ba7742013-02-27 14:36:02 -08004850 if (VOS_FTM_MODE == hdd_get_conparam())
4851 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004852 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
4853 {
4854 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
4855 goto err_free_hdd_context;
4856 }
4857 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
4858 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08004859 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004860
Jeff Johnson88ba7742013-02-27 14:36:02 -08004861 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07004862 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4863 {
4864 status = vos_watchdog_open(pVosContext,
4865 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
4866
4867 if(!VOS_IS_STATUS_SUCCESS( status ))
4868 {
4869 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004870 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07004871 }
4872 }
4873
4874 pHddCtx->isLogpInProgress = FALSE;
4875 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4876
Jeff Johnson295189b2012-06-20 16:38:30 -07004877 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
4878 if(!VOS_IS_STATUS_SUCCESS(status))
4879 {
4880 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004881 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004882 }
4883
Jeff Johnson295189b2012-06-20 16:38:30 -07004884 status = vos_open( &pVosContext, 0);
4885 if ( !VOS_IS_STATUS_SUCCESS( status ))
4886 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004887 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
4888 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07004889 }
4890
Jeff Johnson295189b2012-06-20 16:38:30 -07004891 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
4892
4893 if ( NULL == pHddCtx->hHal )
4894 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004895 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004896 goto err_vosclose;
4897 }
4898
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004899 status = vos_preStart( pHddCtx->pvosContext );
4900 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4901 {
4902 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
4903 goto err_vosclose;
4904 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004905
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004906 /* Note that the vos_preStart() sequence triggers the cfg download.
4907 The cfg download must occur before we update the SME config
4908 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07004909 status = hdd_set_sme_config( pHddCtx );
4910
4911 if ( VOS_STATUS_SUCCESS != status )
4912 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004913 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
4914 goto err_vosclose;
4915 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004916
4917 //Initialize the WMM module
4918 status = hdd_wmm_init(pHddCtx);
4919 if (!VOS_IS_STATUS_SUCCESS(status))
4920 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004921 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004922 goto err_vosclose;
4923 }
4924
Jeff Johnson295189b2012-06-20 16:38:30 -07004925 /* In the integrated architecture we update the configuration from
4926 the INI file and from NV before vOSS has been started so that
4927 the final contents are available to send down to the cCPU */
4928
4929 // Apply the cfg.ini to cfg.dat
4930 if (FALSE == hdd_update_config_dat(pHddCtx))
4931 {
4932 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
4933 goto err_vosclose;
4934 }
4935
4936 // Apply the NV to cfg.dat
4937 /* Prima Update MAC address only at here */
4938 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
4939 {
4940#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
4941 /* There was not a valid set of MAC Addresses in NV. See if the
4942 default addresses were modified by the cfg.ini settings. If so,
4943 we'll use them, but if not, we'll autogenerate a set of MAC
4944 addresses based upon the device serial number */
4945
4946 static const v_MACADDR_t default_address =
4947 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
4948 unsigned int serialno;
4949 int i;
4950
4951 serialno = wcnss_get_serial_number();
4952 if ((0 != serialno) &&
4953 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
4954 sizeof(default_address))))
4955 {
4956 /* cfg.ini has the default address, invoke autogen logic */
4957
4958 /* MAC address has 3 bytes of OUI so we have a maximum of 3
4959 bytes of the serial number that can be used to generate
4960 the other 3 bytes of the MAC address. Mask off all but
4961 the lower 3 bytes (this will also make sure we don't
4962 overflow in the next step) */
4963 serialno &= 0x00FFFFFF;
4964
4965 /* we need a unique address for each session */
4966 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
4967
4968 /* autogen all addresses */
4969 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4970 {
4971 /* start with the entire default address */
4972 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
4973 /* then replace the lower 3 bytes */
4974 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
4975 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
4976 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
4977
4978 serialno++;
4979 }
4980
4981 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
4982 MAC_ADDRESS_STR,
4983 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4984 }
4985 else
4986#endif //WLAN_AUTOGEN_MACADDR_FEATURE
4987 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004988 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004989 "%s: Invalid MAC address in NV, using MAC from ini file "
4990 MAC_ADDRESS_STR, __func__,
4991 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4992 }
4993 }
4994 {
4995 eHalStatus halStatus;
4996 // Set the MAC Address
4997 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
4998 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
4999 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5000 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5001
5002 if (!HAL_STATUS_SUCCESS( halStatus ))
5003 {
5004 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5005 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005006 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005007 }
5008 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005009
5010 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5011 Note: Firmware image will be read and downloaded inside vos_start API */
5012 status = vos_start( pHddCtx->pvosContext );
5013 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5014 {
5015 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5016 goto err_vosclose;
5017 }
5018
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005019 /* Exchange capability info between Host and FW and also get versioning info from FW */
5020 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005021
5022 status = hdd_post_voss_start_config( pHddCtx );
5023 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5024 {
5025 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5026 __func__);
5027 goto err_vosstop;
5028 }
5029
Jeff Johnson295189b2012-06-20 16:38:30 -07005030 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5031 {
5032 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5033 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5034 }
5035 else
5036 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005037 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5038 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5039 if (pAdapter != NULL)
5040 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305041 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005042 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305043 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5044 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5045 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005046
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305047 /* Generate the P2P Device Address. This consists of the device's
5048 * primary MAC address with the locally administered bit set.
5049 */
5050 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005051 }
5052 else
5053 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305054 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5055 if (p2p_dev_addr != NULL)
5056 {
5057 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5058 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5059 }
5060 else
5061 {
5062 hddLog(VOS_TRACE_LEVEL_FATAL,
5063 "%s: Failed to allocate mac_address for p2p_device",
5064 __func__);
5065 goto err_close_adapter;
5066 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005067 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005068
5069 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5070 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5071 if ( NULL == pP2pAdapter )
5072 {
5073 hddLog(VOS_TRACE_LEVEL_FATAL,
5074 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005075 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005076 goto err_close_adapter;
5077 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005078 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005079 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005080
5081 if( pAdapter == NULL )
5082 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005083 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5084 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005085 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005086
Jeff Johnson295189b2012-06-20 16:38:30 -07005087#ifdef WLAN_BTAMP_FEATURE
5088 vStatus = WLANBAP_Open(pVosContext);
5089 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5090 {
5091 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5092 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005093 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005094 }
5095
5096 vStatus = BSL_Init(pVosContext);
5097 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5098 {
5099 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5100 "%s: Failed to Init BSL",__func__);
5101 goto err_bap_close;
5102 }
5103 vStatus = WLANBAP_Start(pVosContext);
5104 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5105 {
5106 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5107 "%s: Failed to start TL",__func__);
5108 goto err_bap_close;
5109 }
5110
5111 pConfig = pHddCtx->cfg_ini;
5112 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5113 status = WLANBAP_SetConfig(&btAmpConfig);
5114
5115#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005116
Jeff Johnson295189b2012-06-20 16:38:30 -07005117#ifdef FEATURE_WLAN_SCAN_PNO
5118 /*SME must send channel update configuration to RIVA*/
5119 sme_UpdateChannelConfig(pHddCtx->hHal);
5120#endif
5121
Jeff Johnson295189b2012-06-20 16:38:30 -07005122 /* Register with platform driver as client for Suspend/Resume */
5123 status = hddRegisterPmOps(pHddCtx);
5124 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5125 {
5126 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5127#ifdef WLAN_BTAMP_FEATURE
5128 goto err_bap_stop;
5129#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005130 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005131#endif //WLAN_BTAMP_FEATURE
5132 }
5133
5134 /* Register TM level change handler function to the platform */
5135 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5136 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5137 {
5138 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5139 goto err_unregister_pmops;
5140 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005141
5142 /* register for riva power on lock to platform driver */
5143 if (req_riva_power_on_lock("wlan"))
5144 {
5145 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5146 __func__);
5147 goto err_unregister_pmops;
5148 }
5149
Jeff Johnson295189b2012-06-20 16:38:30 -07005150 // register net device notifier for device change notification
5151 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5152
5153 if(ret < 0)
5154 {
5155 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5156 goto err_free_power_on_lock;
5157 }
5158
5159 //Initialize the nlink service
5160 if(nl_srv_init() != 0)
5161 {
5162 hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
5163 goto err_reg_netdev;
5164 }
5165
5166 //Initialize the BTC service
5167 if(btc_activate_service(pHddCtx) != 0)
5168 {
5169 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5170 goto err_nl_srv;
5171 }
5172
5173#ifdef PTT_SOCK_SVC_ENABLE
5174 //Initialize the PTT service
5175 if(ptt_sock_activate_svc(pHddCtx) != 0)
5176 {
5177 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5178 goto err_nl_srv;
5179 }
5180#endif
5181
Jeff Johnson295189b2012-06-20 16:38:30 -07005182 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005183 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005184 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005185 /* Action frame registered in one adapter which will
5186 * applicable to all interfaces
5187 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005188 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005189 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005190
5191 mutex_init(&pHddCtx->sap_lock);
5192
5193 pHddCtx->isLoadUnloadInProgress = FALSE;
5194
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005195#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005196#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5197 /* Initialize the wake lcok */
5198 wake_lock_init(&pHddCtx->rx_wake_lock,
5199 WAKE_LOCK_SUSPEND,
5200 "qcom_rx_wakelock");
5201#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005202 /* Initialize the wake lcok */
5203 wake_lock_init(&pHddCtx->sap_wake_lock,
5204 WAKE_LOCK_SUSPEND,
5205 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005206#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005207
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005208 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5209 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005210
5211 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5212 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005213
5214 // Initialize the restart logic
5215 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305216
Jeff Johnson295189b2012-06-20 16:38:30 -07005217 goto success;
5218
5219err_nl_srv:
5220 nl_srv_exit();
5221
5222err_reg_netdev:
5223 unregister_netdevice_notifier(&hdd_netdev_notifier);
5224
5225err_free_power_on_lock:
5226 free_riva_power_on_lock("wlan");
5227
5228err_unregister_pmops:
5229 hddDevTmUnregisterNotifyCallback(pHddCtx);
5230 hddDeregisterPmOps(pHddCtx);
5231
5232#ifdef WLAN_BTAMP_FEATURE
5233err_bap_stop:
5234 WLANBAP_Stop(pVosContext);
5235#endif
5236
5237#ifdef WLAN_BTAMP_FEATURE
5238err_bap_close:
5239 WLANBAP_Close(pVosContext);
5240#endif
5241
Jeff Johnson295189b2012-06-20 16:38:30 -07005242err_close_adapter:
5243 hdd_close_all_adapters( pHddCtx );
5244
5245err_vosstop:
5246 vos_stop(pVosContext);
5247
5248err_vosclose:
5249 status = vos_sched_close( pVosContext );
5250 if (!VOS_IS_STATUS_SUCCESS(status)) {
5251 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5252 "%s: Failed to close VOSS Scheduler", __func__);
5253 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5254 }
5255 vos_close(pVosContext );
5256
Jeff Johnson295189b2012-06-20 16:38:30 -07005257err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005258 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005259
5260err_wdclose:
5261 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5262 vos_watchdog_close(pVosContext);
5263
Jeff Johnson295189b2012-06-20 16:38:30 -07005264err_wiphy_reg:
5265 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005266
5267err_config:
5268 kfree(pHddCtx->cfg_ini);
5269 pHddCtx->cfg_ini= NULL;
5270
5271err_free_hdd_context:
5272 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005273 wiphy_free(wiphy) ;
5274 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005275 VOS_BUG(1);
5276
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005277 if (hdd_is_ssr_required())
5278 {
5279 /* WDI timeout had happened during load, so SSR is needed here */
5280 subsystem_restart("wcnss");
5281 msleep(5000);
5282 }
5283 hdd_set_ssr_required (VOS_FALSE);
5284
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005285 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005286
5287success:
5288 EXIT();
5289 return 0;
5290}
5291
5292/**---------------------------------------------------------------------------
5293
Jeff Johnson32d95a32012-09-10 13:15:23 -07005294 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07005295
Jeff Johnson32d95a32012-09-10 13:15:23 -07005296 This is the driver entry point - called in different timeline depending
5297 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07005298
5299 \param - None
5300
5301 \return - 0 for success, non zero for failure
5302
5303 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07005304static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005305{
5306 VOS_STATUS status;
5307 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005308 struct device *dev = NULL;
5309 int ret_status = 0;
5310
5311 ENTER();
5312
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005313#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005314 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07005315#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005316
5317 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
5318 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
5319
5320 //Power Up Libra WLAN card first if not already powered up
5321 status = vos_chipPowerUp(NULL,NULL,NULL);
5322 if (!VOS_IS_STATUS_SUCCESS(status))
5323 {
5324 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
5325 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005326 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005327 }
5328
Jeff Johnson295189b2012-06-20 16:38:30 -07005329#ifdef ANI_BUS_TYPE_PCI
5330
5331 dev = wcnss_wlan_get_device();
5332
5333#endif // ANI_BUS_TYPE_PCI
5334
5335#ifdef ANI_BUS_TYPE_PLATFORM
5336 dev = wcnss_wlan_get_device();
5337#endif // ANI_BUS_TYPE_PLATFORM
5338
5339
5340 do {
5341 if (NULL == dev) {
5342 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
5343 ret_status = -1;
5344 break;
5345 }
5346
5347#ifdef MEMORY_DEBUG
5348 vos_mem_init();
5349#endif
5350
5351#ifdef TIMER_MANAGER
5352 vos_timer_manager_init();
5353#endif
5354
5355 /* Preopen VOSS so that it is ready to start at least SAL */
5356 status = vos_preOpen(&pVosContext);
5357
5358 if (!VOS_IS_STATUS_SUCCESS(status))
5359 {
5360 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
5361 ret_status = -1;
5362 break;
5363 }
5364
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005365#ifndef MODULE
5366 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
5367 */
5368 hdd_set_conparam((v_UINT_t)con_mode);
5369#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005370
5371 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005372 if (hdd_wlan_startup(dev))
5373 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005374 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005375 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005376 vos_preClose( &pVosContext );
5377 ret_status = -1;
5378 break;
5379 }
5380
5381 /* Cancel the vote for XO Core ON
5382 * This is done here for safety purposes in case we re-initialize without turning
5383 * it OFF in any error scenario.
5384 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005385 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07005386 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005387 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07005388 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5389 {
5390 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
5391 " Power consumed will be high\n");
5392 }
5393 } while (0);
5394
5395 if (0 != ret_status)
5396 {
5397 //Assert Deep sleep signal now to put Libra HW in lowest power state
5398 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5399 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
5400
5401 //Vote off any PMIC voltage supplies
5402 vos_chipPowerDown(NULL, NULL, NULL);
5403#ifdef TIMER_MANAGER
5404 vos_timer_exit();
5405#endif
5406#ifdef MEMORY_DEBUG
5407 vos_mem_exit();
5408#endif
5409
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005410#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005411 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005412#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005413 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
5414 }
5415 else
5416 {
5417 //Send WLAN UP indication to Nlink Service
5418 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
5419
5420 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
5421
5422 }
5423
5424 EXIT();
5425
5426 return ret_status;
5427}
5428
Jeff Johnson32d95a32012-09-10 13:15:23 -07005429/**---------------------------------------------------------------------------
5430
5431 \brief hdd_module_init() - Init Function
5432
5433 This is the driver entry point (invoked when module is loaded using insmod)
5434
5435 \param - None
5436
5437 \return - 0 for success, non zero for failure
5438
5439 --------------------------------------------------------------------------*/
5440#ifdef MODULE
5441static int __init hdd_module_init ( void)
5442{
5443 return hdd_driver_init();
5444}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005445#else /* #ifdef MODULE */
5446static int __init hdd_module_init ( void)
5447{
5448 /* Driver initialization is delayed to fwpath_changed_handler */
5449 return 0;
5450}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005451#endif /* #ifdef MODULE */
5452
Jeff Johnson295189b2012-06-20 16:38:30 -07005453
5454/**---------------------------------------------------------------------------
5455
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005456 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005457
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005458 This is the driver exit point (invoked when module is unloaded using rmmod
5459 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07005460
5461 \param - None
5462
5463 \return - None
5464
5465 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005466static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005467{
5468 hdd_context_t *pHddCtx = NULL;
5469 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005470
5471 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
5472
5473 //Get the global vos context
5474 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5475
5476 if(!pVosContext)
5477 {
5478 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
5479 goto done;
5480 }
5481
5482 //Get the HDD context.
5483 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
5484
5485 if(!pHddCtx)
5486 {
5487 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
5488 }
5489 else
5490 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005491 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07005492 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07005493 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
5494 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07005495 }
5496
5497 pHddCtx->isLoadUnloadInProgress = TRUE;
5498 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5499
5500 //Do all the cleanup before deregistering the driver
5501 hdd_wlan_exit(pHddCtx);
5502 }
5503
Jeff Johnson295189b2012-06-20 16:38:30 -07005504 vos_preClose( &pVosContext );
5505
5506#ifdef TIMER_MANAGER
5507 vos_timer_exit();
5508#endif
5509#ifdef MEMORY_DEBUG
5510 vos_mem_exit();
5511#endif
5512
5513done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005514#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005515 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005516#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005517 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
5518}
5519
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005520/**---------------------------------------------------------------------------
5521
5522 \brief hdd_module_exit() - Exit function
5523
5524 This is the driver exit point (invoked when module is unloaded using rmmod)
5525
5526 \param - None
5527
5528 \return - None
5529
5530 --------------------------------------------------------------------------*/
5531static void __exit hdd_module_exit(void)
5532{
5533 hdd_driver_exit();
5534}
5535
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005536#ifdef MODULE
5537static int fwpath_changed_handler(const char *kmessage,
5538 struct kernel_param *kp)
5539{
5540 /* nothing to do when driver is DLKM */
5541 return 0;
5542}
5543
5544static int con_mode_handler(const char *kmessage,
5545 struct kernel_param *kp)
5546{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07005547 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005548}
5549#else /* #ifdef MODULE */
5550/**---------------------------------------------------------------------------
5551
5552 \brief fwpath_changed_handler() - Handler Function
5553
5554 This is the driver entry point
5555 - delayed driver initialization when driver is statically linked
5556 - invoked when module parameter fwpath is modified from userpspace to signal
5557 initializing the WLAN driver
5558
5559 \return - 0 for success, non zero for failure
5560
5561 --------------------------------------------------------------------------*/
5562static int fwpath_changed_handler(const char *kmessage,
5563 struct kernel_param *kp)
5564{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005565 int ret_status;
5566
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005567 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005568 ret_status = hdd_driver_init();
5569 wlan_hdd_inited = ret_status ? 0 : 1;
5570 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005571 }
5572
5573 hdd_driver_exit();
5574
5575 msleep(200);
5576
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005577 ret_status = hdd_driver_init();
5578 wlan_hdd_inited = ret_status ? 0 : 1;
5579 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005580}
5581
Jeff Johnson295189b2012-06-20 16:38:30 -07005582/**---------------------------------------------------------------------------
5583
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005584 \brief con_mode_handler() -
5585
5586 Handler function for module param con_mode when it is changed by userspace
5587 Dynamically linked - do nothing
5588 Statically linked - exit and init driver, as in rmmod and insmod
5589
5590 \param -
5591
5592 \return -
5593
5594 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005595static int con_mode_handler(const char *kmessage,
5596 struct kernel_param *kp)
5597{
5598 int ret = param_set_int(kmessage, kp);
5599
5600 if (ret)
5601 return ret;
5602
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005603 return fwpath_changed_handler(kmessage, kp);
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005604}
5605#endif /* #ifdef MODULE */
5606
5607/**---------------------------------------------------------------------------
5608
Jeff Johnson295189b2012-06-20 16:38:30 -07005609 \brief hdd_get_conparam() -
5610
5611 This is the driver exit point (invoked when module is unloaded using rmmod)
5612
5613 \param - None
5614
5615 \return - tVOS_CON_MODE
5616
5617 --------------------------------------------------------------------------*/
5618tVOS_CON_MODE hdd_get_conparam ( void )
5619{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005620#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07005621 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005622#else
5623 return (tVOS_CON_MODE)curr_con_mode;
5624#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005625}
5626void hdd_set_conparam ( v_UINT_t newParam )
5627{
5628 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005629#ifndef MODULE
5630 curr_con_mode = con_mode;
5631#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005632}
5633/**---------------------------------------------------------------------------
5634
5635 \brief hdd_softap_sta_deauth() - function
5636
5637 This to take counter measure to handle deauth req from HDD
5638
5639 \param - pAdapter - Pointer to the HDD
5640
5641 \param - enable - boolean value
5642
5643 \return - None
5644
5645 --------------------------------------------------------------------------*/
5646
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005647VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07005648{
Jeff Johnson295189b2012-06-20 16:38:30 -07005649 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005650 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07005651
5652 ENTER();
5653
5654 hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5655
5656 //Ignore request to deauth bcmc station
5657 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005658 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005659
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005660 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07005661
5662 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005663 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005664}
5665
5666/**---------------------------------------------------------------------------
5667
5668 \brief hdd_softap_sta_disassoc() - function
5669
5670 This to take counter measure to handle deauth req from HDD
5671
5672 \param - pAdapter - Pointer to the HDD
5673
5674 \param - enable - boolean value
5675
5676 \return - None
5677
5678 --------------------------------------------------------------------------*/
5679
5680void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
5681{
5682 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5683
5684 ENTER();
5685
5686 hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5687
5688 //Ignore request to disassoc bcmc station
5689 if( pDestMacAddress[0] & 0x1 )
5690 return;
5691
5692 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
5693}
5694
5695void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
5696{
5697 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5698
5699 ENTER();
5700
5701 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5702
5703 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
5704}
5705
Jeff Johnson295189b2012-06-20 16:38:30 -07005706/**---------------------------------------------------------------------------
5707 *
5708 * \brief hdd_get__concurrency_mode() -
5709 *
5710 *
5711 * \param - None
5712 *
5713 * \return - CONCURRENCY MODE
5714 *
5715 * --------------------------------------------------------------------------*/
5716tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
5717{
5718 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5719 hdd_context_t *pHddCtx;
5720
5721 if (NULL != pVosContext)
5722 {
5723 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5724 if (NULL != pHddCtx)
5725 {
5726 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
5727 }
5728 }
5729
5730 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005731 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005732 return VOS_STA;
5733}
5734
5735/* Decide whether to allow/not the apps power collapse.
5736 * Allow apps power collapse if we are in connected state.
5737 * if not, allow only if we are in IMPS */
5738v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
5739{
5740 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08005741 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005742 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07005743 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5744 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5745 hdd_adapter_t *pAdapter = NULL;
5746 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08005747 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005748
Jeff Johnson295189b2012-06-20 16:38:30 -07005749 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5750 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005751
Yathish9f22e662012-12-10 14:21:35 -08005752 concurrent_state = hdd_get_concurrency_mode();
5753
5754#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5755 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
5756 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
5757 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
5758 return TRUE;
5759#endif
5760
Jeff Johnson295189b2012-06-20 16:38:30 -07005761 /*loop through all adapters. TBD fix for Concurrency */
5762 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5763 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5764 {
5765 pAdapter = pAdapterNode->pAdapter;
5766 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
5767 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5768 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005769 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07005770 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08005771 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005772 (eANI_BOOLEAN_TRUE == scanRspPending) ||
5773 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07005774 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005775 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005776 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
5777 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07005778 return FALSE;
5779 }
5780 }
5781 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5782 pAdapterNode = pNext;
5783 }
5784 return TRUE;
5785}
5786
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08005787/* Decides whether to send suspend notification to Riva
5788 * if any adapter is in BMPS; then it is required */
5789v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
5790{
5791 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
5792 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5793
5794 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
5795 {
5796 return TRUE;
5797 }
5798 return FALSE;
5799}
5800
Jeff Johnson295189b2012-06-20 16:38:30 -07005801void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5802{
5803 switch(mode)
5804 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005805 case VOS_STA_MODE:
5806 case VOS_P2P_CLIENT_MODE:
5807 case VOS_P2P_GO_MODE:
5808 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07005809 pHddCtx->concurrency_mode |= (1 << mode);
5810 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07005811 break;
5812 default:
5813 break;
5814
5815 }
5816 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5817 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5818}
5819
5820
5821void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5822{
5823 switch(mode)
5824 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005825 case VOS_STA_MODE:
5826 case VOS_P2P_CLIENT_MODE:
5827 case VOS_P2P_GO_MODE:
5828 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005829 pHddCtx->no_of_sessions[mode]--;
5830 if (!(pHddCtx->no_of_sessions[mode]))
5831 pHddCtx->concurrency_mode &= (~(1 << mode));
5832 break;
5833 default:
5834 break;
5835 }
5836 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5837 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5838}
5839
Jeff Johnsone7245742012-09-05 17:12:55 -07005840/**---------------------------------------------------------------------------
5841 *
5842 * \brief wlan_hdd_restart_init
5843 *
5844 * This function initalizes restart timer/flag. An internal function.
5845 *
5846 * \param - pHddCtx
5847 *
5848 * \return - None
5849 *
5850 * --------------------------------------------------------------------------*/
5851
5852static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
5853{
5854 /* Initialize */
5855 pHddCtx->hdd_restart_retries = 0;
5856 atomic_set(&pHddCtx->isRestartInProgress, 0);
5857 vos_timer_init(&pHddCtx->hdd_restart_timer,
5858 VOS_TIMER_TYPE_SW,
5859 wlan_hdd_restart_timer_cb,
5860 pHddCtx);
5861}
5862/**---------------------------------------------------------------------------
5863 *
5864 * \brief wlan_hdd_restart_deinit
5865 *
5866 * This function cleans up the resources used. An internal function.
5867 *
5868 * \param - pHddCtx
5869 *
5870 * \return - None
5871 *
5872 * --------------------------------------------------------------------------*/
5873
5874static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
5875{
5876
5877 VOS_STATUS vos_status;
5878 /* Block any further calls */
5879 atomic_set(&pHddCtx->isRestartInProgress, 1);
5880 /* Cleanup */
5881 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
5882 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005883 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005884 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
5885 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005886 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005887
5888}
5889
5890/**---------------------------------------------------------------------------
5891 *
5892 * \brief wlan_hdd_framework_restart
5893 *
5894 * This function uses a cfg80211 API to start a framework initiated WLAN
5895 * driver module unload/load.
5896 *
5897 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
5898 *
5899 *
5900 * \param - pHddCtx
5901 *
5902 * \return - VOS_STATUS_SUCCESS: Success
5903 * VOS_STATUS_E_EMPTY: Adapter is Empty
5904 * VOS_STATUS_E_NOMEM: No memory
5905
5906 * --------------------------------------------------------------------------*/
5907
5908static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
5909{
5910 VOS_STATUS status = VOS_STATUS_SUCCESS;
5911 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5912 int len = (sizeof (struct ieee80211_mgmt));
5913 struct ieee80211_mgmt *mgmt = NULL;
5914
5915 /* Prepare the DEAUTH managment frame with reason code */
5916 mgmt = kzalloc(len, GFP_KERNEL);
5917 if(mgmt == NULL)
5918 {
5919 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1250df42012-12-10 14:31:52 -08005920 "%s: memory allocation failed (%d bytes)", __func__, len);
Jeff Johnsone7245742012-09-05 17:12:55 -07005921 return VOS_STATUS_E_NOMEM;
5922 }
5923 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
5924
5925 /* Iterate over all adapters/devices */
5926 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5927 do
5928 {
5929 if( (status == VOS_STATUS_SUCCESS) &&
5930 pAdapterNode &&
5931 pAdapterNode->pAdapter)
5932 {
5933 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5934 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
5935 pAdapterNode->pAdapter->dev->name,
5936 pAdapterNode->pAdapter->device_mode,
5937 pHddCtx->hdd_restart_retries + 1);
5938 /*
5939 * CFG80211 event to restart the driver
5940 *
5941 * 'cfg80211_send_unprot_deauth' sends a
5942 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
5943 * of SME(Linux Kernel) state machine.
5944 *
5945 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
5946 * the driver.
5947 *
5948 */
5949
5950 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
5951 }
5952 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5953 pAdapterNode = pNext;
5954 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
5955
5956
5957 /* Free the allocated management frame */
5958 kfree(mgmt);
5959
5960 /* Retry until we unload or reach max count */
5961 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
5962 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
5963
5964 return status;
5965
5966}
5967/**---------------------------------------------------------------------------
5968 *
5969 * \brief wlan_hdd_restart_timer_cb
5970 *
5971 * Restart timer callback. An internal function.
5972 *
5973 * \param - User data:
5974 *
5975 * \return - None
5976 *
5977 * --------------------------------------------------------------------------*/
5978
5979void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
5980{
5981 hdd_context_t *pHddCtx = usrDataForCallback;
5982 wlan_hdd_framework_restart(pHddCtx);
5983 return;
5984
5985}
5986
5987
5988/**---------------------------------------------------------------------------
5989 *
5990 * \brief wlan_hdd_restart_driver
5991 *
5992 * This function sends an event to supplicant to restart the WLAN driver.
5993 *
5994 * This function is called from vos_wlanRestart.
5995 *
5996 * \param - pHddCtx
5997 *
5998 * \return - VOS_STATUS_SUCCESS: Success
5999 * VOS_STATUS_E_EMPTY: Adapter is Empty
6000 * VOS_STATUS_E_ALREADY: Request already in progress
6001
6002 * --------------------------------------------------------------------------*/
6003VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6004{
6005 VOS_STATUS status = VOS_STATUS_SUCCESS;
6006
6007 /* A tight check to make sure reentrancy */
6008 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6009 {
6010 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6011 "%s: WLAN restart is already in progress", __func__);
6012
6013 return VOS_STATUS_E_ALREADY;
6014 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006015 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006016#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006017 wcnss_reset_intr();
6018#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006019
Jeff Johnsone7245742012-09-05 17:12:55 -07006020 return status;
6021}
6022
6023
Jeff Johnson295189b2012-06-20 16:38:30 -07006024//Register the module init/exit functions
6025module_init(hdd_module_init);
6026module_exit(hdd_module_exit);
6027
6028MODULE_LICENSE("Dual BSD/GPL");
6029MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6030MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6031
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006032module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6033 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006034
6035module_param_call(fwpath, fwpath_changed_handler, param_get_string, fwpath,
6036 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);