blob: f610104f3681f383f0d92a319a55bbff81b54bb2 [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;
1072 goto exit;
1073 }
1074
1075 /* if the channel number is different from operating channel then
1076 no need to send action frame */
1077 if (channel != pHddStaCtx->conn_info.operationChannel)
1078 {
1079 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1080 "%s: channel(%d) is different from operating channel(%d)",
1081 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1082 ret = -EINVAL;
1083 goto exit;
1084 }
1085 chan.center_freq = sme_ChnToFreq(channel);
1086
1087 finalLen = bufLen + 24;
1088 finalBuf = vos_mem_malloc(finalLen);
1089 if (NULL == finalBuf)
1090 {
1091 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1092 ret = -ENOMEM;
1093 goto exit;
1094 }
1095 vos_mem_zero(finalBuf, finalLen);
1096
1097 /* Fill subtype */
1098 temp = SIR_MAC_MGMT_ACTION << 4;
1099 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1100
1101 /* Fill type */
1102 temp = SIR_MAC_MGMT_FRAME;
1103 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1104
1105 /* Fill destination address (bssid of the AP) */
1106 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1107
1108 /* Fill BSSID (STA mac address) */
1109 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1110
1111 /* Fill source address (STA mac address) */
1112 vos_mem_copy(finalBuf + 16, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1113
1114 /* Fill received buffer from 24th address */
1115 vos_mem_copy(finalBuf + 24, buf, bufLen);
1116
1117 wlan_hdd_action( NULL, dev, &chan, 0, NL80211_CHAN_HT20,
1118 1, dwellTime, finalBuf, finalLen, 1,
1119 1, &cookie );
1120 vos_mem_free(finalBuf);
1121 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001122 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1123 {
1124 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1125 char extra[32];
1126 tANI_U8 len = 0;
1127
1128 /* value is interms of msec */
1129 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1130 if (copy_to_user(priv_data.buf, &extra, len + 1))
1131 {
1132 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1133 "%s: failed to copy data to user buffer", __func__);
1134 ret = -EFAULT;
1135 goto exit;
1136 }
1137 }
1138 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1139 {
1140 tANI_U8 *value = command;
1141 tANI_U8 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
1142
1143 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1144 value = value + 19;
1145 /* Convert the value from ascii to integer */
1146 ret = kstrtou8(value, 10, &maxTime);
1147 if (ret < 0)
1148 {
1149 /* If the input value is greater than max value of datatype, then also
1150 kstrtou8 fails */
1151 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1152 "%s: kstrtou8 failed range [%d - %d]", __func__,
1153 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1154 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1155 ret = -EINVAL;
1156 goto exit;
1157 }
1158
1159 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1160 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1161 {
1162 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1163 "lfr mode value %d is out of range"
1164 " (Min: %d Max: %d)", maxTime,
1165 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1166 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1167 ret = -EINVAL;
1168 goto exit;
1169 }
1170
1171 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1172 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1173
1174 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
1175 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1176 }
1177 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1178 {
1179 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1180 char extra[32];
1181 tANI_U8 len = 0;
1182
1183 /* value is interms of msec */
1184 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1185 if (copy_to_user(priv_data.buf, &extra, len + 1))
1186 {
1187 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1188 "%s: failed to copy data to user buffer", __func__);
1189 ret = -EFAULT;
1190 goto exit;
1191 }
1192 }
1193 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1194 {
1195 tANI_U8 *value = command;
1196 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1197
1198 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1199 value = value + 16;
1200 /* Convert the value from ascii to integer */
1201 ret = kstrtou16(value, 10, &val);
1202 if (ret < 0)
1203 {
1204 /* If the input value is greater than max value of datatype, then also
1205 kstrtou16 fails */
1206 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1207 "%s: kstrtou16 failed range [%d - %d]", __func__,
1208 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1209 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1210 ret = -EINVAL;
1211 goto exit;
1212 }
1213
1214 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1215 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1216 {
1217 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1218 "scan home time value %d is out of range"
1219 " (Min: %d Max: %d)", val,
1220 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1221 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1222 ret = -EINVAL;
1223 goto exit;
1224 }
1225
1226 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1227 "%s: Received Command to change scan home time = %d", __func__, val);
1228
1229 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1230 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1231 }
1232 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1233 {
1234 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1235 char extra[32];
1236 tANI_U8 len = 0;
1237
1238 /* value is interms of msec */
1239 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1240 if (copy_to_user(priv_data.buf, &extra, len + 1))
1241 {
1242 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1243 "%s: failed to copy data to user buffer", __func__);
1244 ret = -EFAULT;
1245 goto exit;
1246 }
1247 }
1248 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1249 {
1250 tANI_U8 *value = command;
1251 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1252
1253 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1254 value = value + 17;
1255 /* Convert the value from ascii to integer */
1256 ret = kstrtou8(value, 10, &val);
1257 if (ret < 0)
1258 {
1259 /* If the input value is greater than max value of datatype, then also
1260 kstrtou8 fails */
1261 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1262 "%s: kstrtou8 failed range [%d - %d]", __func__,
1263 CFG_ROAM_INTRA_BAND_MIN,
1264 CFG_ROAM_INTRA_BAND_MAX);
1265 ret = -EINVAL;
1266 goto exit;
1267 }
1268
1269 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1270 (val > CFG_ROAM_INTRA_BAND_MAX))
1271 {
1272 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1273 "intra band mode value %d is out of range"
1274 " (Min: %d Max: %d)", val,
1275 CFG_ROAM_INTRA_BAND_MIN,
1276 CFG_ROAM_INTRA_BAND_MAX);
1277 ret = -EINVAL;
1278 goto exit;
1279 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001280 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1281 "%s: Received Command to change intra band = %d", __func__, val);
1282
1283 pHddCtx->cfg_ini->nRoamIntraBand = val;
1284 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1285 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001286 else if (strncmp(command, "SETWESMODE", 10) == 0)
1287 {
1288 tANI_U8 *value = command;
1289 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
1290
1291 /* Move pointer to ahead of SETWESMODE<delimiter> */
1292 value = value + 11;
1293 /* Convert the value from ascii to integer */
1294 ret = kstrtou8(value, 10, &wesMode);
1295 if (ret < 0)
1296 {
1297 /* If the input value is greater than max value of datatype, then also
1298 kstrtou8 fails */
1299 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1300 "%s: kstrtou8 failed range [%d - %d]", __func__,
1301 CFG_ENABLE_WES_MODE_NAME_MIN,
1302 CFG_ENABLE_WES_MODE_NAME_MAX);
1303 ret = -EINVAL;
1304 goto exit;
1305 }
1306
1307 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
1308 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
1309 {
1310 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1311 "WES Mode value %d is out of range"
1312 " (Min: %d Max: %d)", wesMode,
1313 CFG_ENABLE_WES_MODE_NAME_MIN,
1314 CFG_ENABLE_WES_MODE_NAME_MAX);
1315 ret = -EINVAL;
1316 goto exit;
1317 }
1318 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1319 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
1320
1321 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
1322 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
1323 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001324 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1325 {
1326 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1327 char extra[32];
1328 tANI_U8 len = 0;
1329
1330 /* value is interms of msec */
1331 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1332 if (copy_to_user(priv_data.buf, &extra, len + 1))
1333 {
1334 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1335 "%s: failed to copy data to user buffer", __func__);
1336 ret = -EFAULT;
1337 goto exit;
1338 }
1339 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001340 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
1341 {
1342 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
1343 char extra[32];
1344 tANI_U8 len = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001345
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001346 len = snprintf(extra, sizeof(extra), "%s %d", command, wesMode);
1347 if (copy_to_user(priv_data.buf, &extra, len + 1))
1348 {
1349 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1350 "%s: failed to copy data to user buffer", __func__);
1351 ret = -EFAULT;
1352 goto exit;
1353 }
1354 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001355#endif
1356#ifdef FEATURE_WLAN_LFR
1357 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1358 {
1359 tANI_U8 *value = command;
1360 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1361
1362 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1363 value = value + 12;
1364 /* Convert the value from ascii to integer */
1365 ret = kstrtou8(value, 10, &lfrMode);
1366 if (ret < 0)
1367 {
1368 /* If the input value is greater than max value of datatype, then also
1369 kstrtou8 fails */
1370 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1371 "%s: kstrtou8 failed range [%d - %d]", __func__,
1372 CFG_LFR_FEATURE_ENABLED_MIN,
1373 CFG_LFR_FEATURE_ENABLED_MAX);
1374 ret = -EINVAL;
1375 goto exit;
1376 }
1377
1378 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1379 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1380 {
1381 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1382 "lfr mode value %d is out of range"
1383 " (Min: %d Max: %d)", lfrMode,
1384 CFG_LFR_FEATURE_ENABLED_MIN,
1385 CFG_LFR_FEATURE_ENABLED_MAX);
1386 ret = -EINVAL;
1387 goto exit;
1388 }
1389
1390 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1391 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1392
1393 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1394 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1395 }
1396#endif
1397#ifdef WLAN_FEATURE_VOWIFI_11R
1398 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1399 {
1400 tANI_U8 *value = command;
1401 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1402
1403 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1404 value = value + 18;
1405 /* Convert the value from ascii to integer */
1406 ret = kstrtou8(value, 10, &ft);
1407 if (ret < 0)
1408 {
1409 /* If the input value is greater than max value of datatype, then also
1410 kstrtou8 fails */
1411 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1412 "%s: kstrtou8 failed range [%d - %d]", __func__,
1413 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1414 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1415 ret = -EINVAL;
1416 goto exit;
1417 }
1418
1419 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1420 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1421 {
1422 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1423 "ft mode value %d is out of range"
1424 " (Min: %d Max: %d)", ft,
1425 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1426 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1427 ret = -EINVAL;
1428 goto exit;
1429 }
1430
1431 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1432 "%s: Received Command to change ft mode = %d", __func__, ft);
1433
1434 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1435 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1436 }
1437#endif
1438#ifdef FEATURE_WLAN_CCX
1439 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1440 {
1441 tANI_U8 *value = command;
1442 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1443
1444 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1445 value = value + 11;
1446 /* Convert the value from ascii to integer */
1447 ret = kstrtou8(value, 10, &ccxMode);
1448 if (ret < 0)
1449 {
1450 /* If the input value is greater than max value of datatype, then also
1451 kstrtou8 fails */
1452 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1453 "%s: kstrtou8 failed range [%d - %d]", __func__,
1454 CFG_CCX_FEATURE_ENABLED_MIN,
1455 CFG_CCX_FEATURE_ENABLED_MAX);
1456 ret = -EINVAL;
1457 goto exit;
1458 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001459 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1460 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1461 {
1462 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1463 "Ccx mode value %d is out of range"
1464 " (Min: %d Max: %d)", ccxMode,
1465 CFG_CCX_FEATURE_ENABLED_MIN,
1466 CFG_CCX_FEATURE_ENABLED_MAX);
1467 ret = -EINVAL;
1468 goto exit;
1469 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001470 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1471 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1472
1473 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1474 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1475 }
1476#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001477 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1478 {
1479 tANI_U8 *value = command;
1480 tANI_BOOLEAN roamScanControl = 0;
1481
1482 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1483 value = value + 19;
1484 /* Convert the value from ascii to integer */
1485 ret = kstrtou8(value, 10, &roamScanControl);
1486 if (ret < 0)
1487 {
1488 /* If the input value is greater than max value of datatype, then also
1489 kstrtou8 fails */
1490 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1491 "%s: kstrtou8 failed ", __func__);
1492 ret = -EINVAL;
1493 goto exit;
1494 }
1495
1496 if (0 != roamScanControl)
1497 {
1498 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1499 "roam scan control invalid value = %d",
1500 roamScanControl);
1501 ret = -EINVAL;
1502 goto exit;
1503 }
1504 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1505 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1506
1507 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1508 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001509#ifdef FEATURE_WLAN_OKC
1510 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1511 {
1512 tANI_U8 *value = command;
1513 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1514
1515 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1516 value = value + 11;
1517 /* Convert the value from ascii to integer */
1518 ret = kstrtou8(value, 10, &okcMode);
1519 if (ret < 0)
1520 {
1521 /* If the input value is greater than max value of datatype, then also
1522 kstrtou8 fails */
1523 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1524 "%s: kstrtou8 failed range [%d - %d]", __func__,
1525 CFG_OKC_FEATURE_ENABLED_MIN,
1526 CFG_OKC_FEATURE_ENABLED_MAX);
1527 ret = -EINVAL;
1528 goto exit;
1529 }
1530
1531 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1532 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1533 {
1534 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1535 "Okc mode value %d is out of range"
1536 " (Min: %d Max: %d)", okcMode,
1537 CFG_OKC_FEATURE_ENABLED_MIN,
1538 CFG_OKC_FEATURE_ENABLED_MAX);
1539 ret = -EINVAL;
1540 goto exit;
1541 }
1542
1543 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1544 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1545
1546 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1547 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001548 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1549 {
1550 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1551 char extra[32];
1552 tANI_U8 len = 0;
1553
1554 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1555 if (copy_to_user(priv_data.buf, &extra, len + 1))
1556 {
1557 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1558 "%s: failed to copy data to user buffer", __func__);
1559 ret = -EFAULT;
1560 goto exit;
1561 }
1562 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001563#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001564 else {
1565 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
1566 __func__, command);
1567 }
1568
Jeff Johnson295189b2012-06-20 16:38:30 -07001569 }
1570exit:
1571 if (command)
1572 {
1573 kfree(command);
1574 }
1575 return ret;
1576}
1577
Srinivas Girigowdade697412013-02-14 16:31:48 -08001578#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1579void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
1580{
1581 eCsrBand band = -1;
1582 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
1583 switch (band)
1584 {
1585 case eCSR_BAND_ALL:
1586 *pBand = WLAN_HDD_UI_BAND_AUTO;
1587 break;
1588
1589 case eCSR_BAND_24:
1590 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
1591 break;
1592
1593 case eCSR_BAND_5G:
1594 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
1595 break;
1596
1597 default:
1598 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
1599 *pBand = -1;
1600 break;
1601 }
1602}
1603
1604/**---------------------------------------------------------------------------
1605
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001606 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
1607
1608 This function parses the send action frame data passed in the format
1609 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
1610
1611 \param - pValue Pointer to input country code revision
1612 \param - pTargetApBssid Pointer to target Ap bssid
1613 \param - pChannel Pointer to the Target AP channel
1614 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
1615 \param - pBuf Pointer to data
1616 \param - pBufLen Pointer to data length
1617
1618 \return - 0 for success non-zero for failure
1619
1620 --------------------------------------------------------------------------*/
1621VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
1622 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
1623{
1624 tANI_U8 *inPtr = pValue;
1625 tANI_U8 *dataEnd;
1626 int tempInt;
1627 int j = 0;
1628 int i = 0;
1629 int v = 0;
1630 tANI_U8 tempBuf[32];
1631 tANI_U8 tempByte = 0;
1632
1633 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1634 /*no argument after the command*/
1635 if (NULL == inPtr)
1636 {
1637 return -EINVAL;
1638 }
1639
1640 /*no space after the command*/
1641 else if (SPACE_ASCII_VALUE != *inPtr)
1642 {
1643 return -EINVAL;
1644 }
1645
1646 /*removing empty spaces*/
1647 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1648
1649 /*no argument followed by spaces*/
1650 if ('\0' == *inPtr)
1651 {
1652 return -EINVAL;
1653 }
1654
1655 /*getting the first argument ie the target AP bssid */
1656 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
1657 {
1658 return -EINVAL;
1659 }
1660 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
1661 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
1662 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
1663
1664 /* point to the next argument */
1665 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1666 /*no argument after the command*/
1667 if (NULL == inPtr) return -EINVAL;
1668
1669 /*removing empty spaces*/
1670 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1671
1672 /*no argument followed by spaces*/
1673 if ('\0' == *inPtr)
1674 {
1675 return -EINVAL;
1676 }
1677
1678 /*getting the next argument ie the channel number */
1679 j = sscanf(inPtr, "%s ", tempBuf);
1680 v = kstrtos32(tempBuf, 10, &tempInt);
1681 if ( v < 0) return -EINVAL;
1682
1683 *pChannel = tempInt;
1684
1685 /* point to the next argument */
1686 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1687 /*no argument after the command*/
1688 if (NULL == inPtr) return -EINVAL;
1689 /*removing empty spaces*/
1690 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1691
1692 /*no argument followed by spaces*/
1693 if ('\0' == *inPtr)
1694 {
1695 return -EINVAL;
1696 }
1697
1698 /*getting the next argument ie the dwell time */
1699 j = sscanf(inPtr, "%s ", tempBuf);
1700 v = kstrtos32(tempBuf, 10, &tempInt);
1701 if ( v < 0) return -EINVAL;
1702
1703 *pDwellTime = tempInt;
1704
1705 /* point to the next argument */
1706 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1707 /*no argument after the command*/
1708 if (NULL == inPtr) return -EINVAL;
1709 /*removing empty spaces*/
1710 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1711
1712 /*no argument followed by spaces*/
1713 if ('\0' == *inPtr)
1714 {
1715 return -EINVAL;
1716 }
1717
1718 /* find the length of data */
1719 dataEnd = inPtr;
1720 while(('\0' != *dataEnd) )
1721 {
1722 dataEnd++;
1723 ++(*pBufLen);
1724 }
1725 if ( *pBufLen <= 0) return -EINVAL;
1726
1727 *pBuf = vos_mem_malloc(sizeof(*pBufLen));
1728 if (NULL == *pBuf)
1729 {
1730 hddLog(VOS_TRACE_LEVEL_FATAL,
1731 "%s: vos_mem_alloc failed ", __func__);
1732 return -EINVAL;
1733 }
1734
1735 /* the buffer received from the upper layer is character buffer,
1736 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
1737 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
1738 and f0 in 3rd location */
1739 for (i = 0, j = 0; j < *pBufLen; j += 2)
1740 {
1741 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
1742 (*pBuf)[i++] = tempByte;
1743 }
1744 *pBufLen = i;
1745 return VOS_STATUS_SUCCESS;
1746}
1747
1748#endif
1749/**---------------------------------------------------------------------------
1750
Srinivas Girigowdade697412013-02-14 16:31:48 -08001751 \brief hdd_parse_countryrev() - HDD Parse country code revision
1752
1753 This function parses the country code revision passed in the format
1754 SETCOUNTRYREV<space><Country code><space>revision
1755
1756 \param - pValue Pointer to input country code revision
1757 \param - pCountryCode Pointer to local output array to record country code
1758 \param - pRevision Pointer to store revision integer number
1759
1760 \return - 0 for success non-zero for failure
1761
1762 --------------------------------------------------------------------------*/
1763VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
1764{
1765 tANI_U8 *inPtr = pValue;
1766 int tempInt;
1767
1768 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1769 /*no argument after the command*/
1770 if (NULL == inPtr)
1771 {
1772 return -EINVAL;
1773 }
1774
1775 /*no space after the command*/
1776 else if (SPACE_ASCII_VALUE != *inPtr)
1777 {
1778 return -EINVAL;
1779 }
1780
1781 /*removing empty spaces*/
1782 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
1783
1784 /*no argument followed by spaces*/
1785 if ('\0' == *inPtr)
1786 {
1787 return -EINVAL;
1788 }
1789
1790 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07001791 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001792
1793 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1794 "Country code is : %s", pCountryCode);
1795
1796 /*inPtr pointing to the beginning of first space after country code */
1797 inPtr = strpbrk( inPtr, " " );
1798 /*no revision number after the country code argument */
1799 if (NULL == inPtr)
1800 {
1801 return -EINVAL;
1802 }
1803
1804 inPtr++;
1805
1806 /*removing empty space*/
1807 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1808
1809 /*no channel list after the number of channels argument and spaces*/
1810 if (0 == strncmp(pCountryCode, "KR", 2))
1811 {
1812 if ('\0' == *inPtr)
1813 {
1814 return -EINVAL;
1815 }
1816
1817 sscanf(inPtr, "%d", &tempInt);
1818 *pRevision = tempInt;
1819 }
1820 else
1821 {
1822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1823 "Revision input is required only for Country KR");
1824 return -EINVAL;
1825 }
1826 return VOS_STATUS_SUCCESS;
1827}
1828
1829/**---------------------------------------------------------------------------
1830
1831 \brief hdd_parse_channellist() - HDD Parse channel list
1832
1833 This function parses the channel list passed in the format
1834 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001835 if the Number of channels (N) does not match with the actual number of channels passed
1836 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
1837 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
1838 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
1839 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08001840
1841 \param - pValue Pointer to input channel list
1842 \param - ChannelList Pointer to local output array to record channel list
1843 \param - pNumChannels Pointer to number of roam scan channels
1844
1845 \return - 0 for success non-zero for failure
1846
1847 --------------------------------------------------------------------------*/
1848VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
1849{
1850 tANI_U8 *inPtr = pValue;
1851 int tempInt;
1852 int j = 0;
1853 int v = 0;
1854 char buf[32];
1855
1856 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1857 /*no argument after the command*/
1858 if (NULL == inPtr)
1859 {
1860 return -EINVAL;
1861 }
1862
1863 /*no space after the command*/
1864 else if (SPACE_ASCII_VALUE != *inPtr)
1865 {
1866 return -EINVAL;
1867 }
1868
1869 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001870 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001871
1872 /*no argument followed by spaces*/
1873 if ('\0' == *inPtr)
1874 {
1875 return -EINVAL;
1876 }
1877
1878 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07001879 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001880 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001881 if ((v < 0) ||
1882 (tempInt <= 0) ||
1883 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
1884 {
1885 return -EINVAL;
1886 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001887
1888 *pNumChannels = tempInt;
1889
1890 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1891 "Number of channels are: %d", *pNumChannels);
1892
1893 for (j = 0; j < (*pNumChannels); j++)
1894 {
1895 /*inPtr pointing to the beginning of first space after number of channels*/
1896 inPtr = strpbrk( inPtr, " " );
1897 /*no channel list after the number of channels argument*/
1898 if (NULL == inPtr)
1899 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001900 if (0 != j)
1901 {
1902 *pNumChannels = j;
1903 return VOS_STATUS_SUCCESS;
1904 }
1905 else
1906 {
1907 return -EINVAL;
1908 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001909 }
1910
1911 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001912 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001913
1914 /*no channel list after the number of channels argument and spaces*/
1915 if ( '\0' == *inPtr )
1916 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001917 if (0 != j)
1918 {
1919 *pNumChannels = j;
1920 return VOS_STATUS_SUCCESS;
1921 }
1922 else
1923 {
1924 return -EINVAL;
1925 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001926 }
1927
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001928 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001929 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001930 if ((v < 0) ||
1931 (tempInt <= 0) ||
1932 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
1933 {
1934 return -EINVAL;
1935 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001936 pChannelList[j] = tempInt;
1937
1938 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1939 "Channel %d added to preferred channel list",
1940 pChannelList[j] );
1941 }
1942
Srinivas Girigowdade697412013-02-14 16:31:48 -08001943 return VOS_STATUS_SUCCESS;
1944}
1945
Jeff Johnson295189b2012-06-20 16:38:30 -07001946/**---------------------------------------------------------------------------
1947
1948 \brief hdd_open() - HDD Open function
1949
1950 This is called in response to ifconfig up
1951
1952 \param - dev Pointer to net_device structure
1953
1954 \return - 0 for success non-zero for failure
1955
1956 --------------------------------------------------------------------------*/
1957int hdd_open (struct net_device *dev)
1958{
1959 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1960 hdd_context_t *pHddCtx;
1961 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1962 VOS_STATUS status;
1963 v_BOOL_t in_standby = TRUE;
1964
1965 if (NULL == pAdapter)
1966 {
1967 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001968 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001969 return -ENODEV;
1970 }
1971
1972 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1973 if (NULL == pHddCtx)
1974 {
1975 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001976 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001977 return -ENODEV;
1978 }
1979
1980 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1981 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1982 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07001983 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
1984 {
1985 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
1986 __func__, pAdapter->device_mode);
1987 in_standby = FALSE;
1988 break;
1989 }
1990 else
1991 {
1992 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1993 pAdapterNode = pNext;
1994 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001995 }
1996
1997 if (TRUE == in_standby)
1998 {
1999 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2000 {
2001 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2002 "wlan out of power save", __func__);
2003 return -EINVAL;
2004 }
2005 }
2006
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002007 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002008 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2009 {
2010 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002011 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002012 /* Enable TX queues only when we are connected */
2013 netif_tx_start_all_queues(dev);
2014 }
2015
2016 return 0;
2017}
2018
2019int hdd_mon_open (struct net_device *dev)
2020{
2021 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2022
2023 if(pAdapter == NULL) {
2024 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002025 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002026 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002027 }
2028
2029 netif_start_queue(dev);
2030
2031 return 0;
2032}
2033/**---------------------------------------------------------------------------
2034
2035 \brief hdd_stop() - HDD stop function
2036
2037 This is called in response to ifconfig down
2038
2039 \param - dev Pointer to net_device structure
2040
2041 \return - 0 for success non-zero for failure
2042
2043 --------------------------------------------------------------------------*/
2044
2045int hdd_stop (struct net_device *dev)
2046{
2047 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2048 hdd_context_t *pHddCtx;
2049 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2050 VOS_STATUS status;
2051 v_BOOL_t enter_standby = TRUE;
2052
2053 ENTER();
2054
2055 if (NULL == pAdapter)
2056 {
2057 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002058 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002059 return -ENODEV;
2060 }
2061
2062 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2063 if (NULL == pHddCtx)
2064 {
2065 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002066 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002067 return -ENODEV;
2068 }
2069
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002070 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002071 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2072 netif_tx_disable(pAdapter->dev);
2073 netif_carrier_off(pAdapter->dev);
2074
2075
2076 /* SoftAP ifaces should never go in power save mode
2077 making sure same here. */
2078 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2079 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002080 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002081 )
2082 {
2083 /* SoftAP mode, so return from here */
2084 EXIT();
2085 return 0;
2086 }
2087
2088 /* Find if any iface is up then
2089 if any iface is up then can't put device to sleep/ power save mode. */
2090 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2091 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2092 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002093 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2094 {
2095 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
2096 "put device to sleep", __func__, pAdapter->device_mode);
2097 enter_standby = FALSE;
2098 break;
2099 }
2100 else
2101 {
2102 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2103 pAdapterNode = pNext;
2104 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002105 }
2106
2107 if (TRUE == enter_standby)
2108 {
2109 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2110 "entering standby", __func__);
2111 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2112 {
2113 /*log and return success*/
2114 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2115 "wlan in power save", __func__);
2116 }
2117 }
2118
2119 EXIT();
2120 return 0;
2121}
2122
2123/**---------------------------------------------------------------------------
2124
2125 \brief hdd_uninit() - HDD uninit function
2126
2127 This is called during the netdev unregister to uninitialize all data
2128associated with the device
2129
2130 \param - dev Pointer to net_device structure
2131
2132 \return - void
2133
2134 --------------------------------------------------------------------------*/
2135static void hdd_uninit (struct net_device *dev)
2136{
2137 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2138
2139 ENTER();
2140
2141 do
2142 {
2143 if (NULL == pAdapter)
2144 {
2145 hddLog(VOS_TRACE_LEVEL_FATAL,
2146 "%s: NULL pAdapter", __func__);
2147 break;
2148 }
2149
2150 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2151 {
2152 hddLog(VOS_TRACE_LEVEL_FATAL,
2153 "%s: Invalid magic", __func__);
2154 break;
2155 }
2156
2157 if (NULL == pAdapter->pHddCtx)
2158 {
2159 hddLog(VOS_TRACE_LEVEL_FATAL,
2160 "%s: NULL pHddCtx", __func__);
2161 break;
2162 }
2163
2164 if (dev != pAdapter->dev)
2165 {
2166 hddLog(VOS_TRACE_LEVEL_FATAL,
2167 "%s: Invalid device reference", __func__);
2168 /* we haven't validated all cases so let this go for now */
2169 }
2170
2171 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2172
2173 /* after uninit our adapter structure will no longer be valid */
2174 pAdapter->dev = NULL;
2175 pAdapter->magic = 0;
2176 } while (0);
2177
2178 EXIT();
2179}
2180
2181/**---------------------------------------------------------------------------
2182
2183 \brief hdd_release_firmware() -
2184
2185 This function calls the release firmware API to free the firmware buffer.
2186
2187 \param - pFileName Pointer to the File Name.
2188 pCtx - Pointer to the adapter .
2189
2190
2191 \return - 0 for success, non zero for failure
2192
2193 --------------------------------------------------------------------------*/
2194
2195VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2196{
2197 VOS_STATUS status = VOS_STATUS_SUCCESS;
2198 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2199 ENTER();
2200
2201
2202 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2203
2204 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2205
2206 if(pHddCtx->fw) {
2207 release_firmware(pHddCtx->fw);
2208 pHddCtx->fw = NULL;
2209 }
2210 else
2211 status = VOS_STATUS_E_FAILURE;
2212 }
2213 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2214 if(pHddCtx->nv) {
2215 release_firmware(pHddCtx->nv);
2216 pHddCtx->nv = NULL;
2217 }
2218 else
2219 status = VOS_STATUS_E_FAILURE;
2220
2221 }
2222
2223 EXIT();
2224 return status;
2225}
2226
2227/**---------------------------------------------------------------------------
2228
2229 \brief hdd_request_firmware() -
2230
2231 This function reads the firmware file using the request firmware
2232 API and returns the the firmware data and the firmware file size.
2233
2234 \param - pfileName - Pointer to the file name.
2235 - pCtx - Pointer to the adapter .
2236 - ppfw_data - Pointer to the pointer of the firmware data.
2237 - pSize - Pointer to the file size.
2238
2239 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2240
2241 --------------------------------------------------------------------------*/
2242
2243
2244VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2245{
2246 int status;
2247 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2248 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2249 ENTER();
2250
2251 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2252
2253 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2254
2255 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2256 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2257 __func__, pfileName);
2258 retval = VOS_STATUS_E_FAILURE;
2259 }
2260
2261 else {
2262 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2263 *pSize = pHddCtx->fw->size;
2264 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2265 __func__, *pSize);
2266 }
2267 }
2268 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2269
2270 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2271
2272 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2273 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2274 __func__, pfileName);
2275 retval = VOS_STATUS_E_FAILURE;
2276 }
2277
2278 else {
2279 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2280 *pSize = pHddCtx->nv->size;
2281 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2282 __func__, *pSize);
2283 }
2284 }
2285
2286 EXIT();
2287 return retval;
2288}
2289/**---------------------------------------------------------------------------
2290 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2291
2292 This is the function invoked by SME to inform the result of a full power
2293 request issued by HDD
2294
2295 \param - callbackcontext - Pointer to cookie
2296 status - result of request
2297
2298 \return - None
2299
2300--------------------------------------------------------------------------*/
2301void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2302{
2303 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2304
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002305 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002306 if(&pHddCtx->full_pwr_comp_var)
2307 {
2308 complete(&pHddCtx->full_pwr_comp_var);
2309 }
2310}
2311
2312/**---------------------------------------------------------------------------
2313
2314 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2315
2316 This is the function invoked by SME to inform the result of BMPS
2317 request issued by HDD
2318
2319 \param - callbackcontext - Pointer to cookie
2320 status - result of request
2321
2322 \return - None
2323
2324--------------------------------------------------------------------------*/
2325void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2326{
2327
2328 struct completion *completion_var = (struct completion*) callbackContext;
2329
2330 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2331 if(completion_var != NULL)
2332 {
2333 complete(completion_var);
2334 }
2335}
2336
2337/**---------------------------------------------------------------------------
2338
2339 \brief hdd_get_cfg_file_size() -
2340
2341 This function reads the configuration file using the request firmware
2342 API and returns the configuration file size.
2343
2344 \param - pCtx - Pointer to the adapter .
2345 - pFileName - Pointer to the file name.
2346 - pBufSize - Pointer to the buffer size.
2347
2348 \return - 0 for success, non zero for failure
2349
2350 --------------------------------------------------------------------------*/
2351
2352VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2353{
2354 int status;
2355 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2356
2357 ENTER();
2358
2359 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2360
2361 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2362 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2363 status = VOS_STATUS_E_FAILURE;
2364 }
2365 else {
2366 *pBufSize = pHddCtx->fw->size;
2367 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2368 release_firmware(pHddCtx->fw);
2369 pHddCtx->fw = NULL;
2370 }
2371
2372 EXIT();
2373 return VOS_STATUS_SUCCESS;
2374}
2375
2376/**---------------------------------------------------------------------------
2377
2378 \brief hdd_read_cfg_file() -
2379
2380 This function reads the configuration file using the request firmware
2381 API and returns the cfg data and the buffer size of the configuration file.
2382
2383 \param - pCtx - Pointer to the adapter .
2384 - pFileName - Pointer to the file name.
2385 - pBuffer - Pointer to the data buffer.
2386 - pBufSize - Pointer to the buffer size.
2387
2388 \return - 0 for success, non zero for failure
2389
2390 --------------------------------------------------------------------------*/
2391
2392VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2393 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2394{
2395 int status;
2396 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2397
2398 ENTER();
2399
2400 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2401
2402 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2403 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2404 return VOS_STATUS_E_FAILURE;
2405 }
2406 else {
2407 if(*pBufSize != pHddCtx->fw->size) {
2408 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2409 "file size", __func__);
2410 release_firmware(pHddCtx->fw);
2411 pHddCtx->fw = NULL;
2412 return VOS_STATUS_E_FAILURE;
2413 }
2414 else {
2415 if(pBuffer) {
2416 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2417 }
2418 release_firmware(pHddCtx->fw);
2419 pHddCtx->fw = NULL;
2420 }
2421 }
2422
2423 EXIT();
2424
2425 return VOS_STATUS_SUCCESS;
2426}
2427
2428/**---------------------------------------------------------------------------
2429
Jeff Johnson295189b2012-06-20 16:38:30 -07002430 \brief hdd_set_mac_address() -
2431
2432 This function sets the user specified mac address using
2433 the command ifconfig wlanX hw ether <mac adress>.
2434
2435 \param - dev - Pointer to the net device.
2436 - addr - Pointer to the sockaddr.
2437 \return - 0 for success, non zero for failure
2438
2439 --------------------------------------------------------------------------*/
2440
2441static int hdd_set_mac_address(struct net_device *dev, void *addr)
2442{
2443 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2444 struct sockaddr *psta_mac_addr = addr;
2445 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2446
2447 ENTER();
2448
2449 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2450
2451#ifdef HDD_SESSIONIZE
2452 // set the MAC address though the STA ID CFG.
2453 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2454 (v_U8_t *)&pAdapter->macAddressCurrent,
2455 sizeof( pAdapter->macAddressCurrent ),
2456 hdd_set_mac_addr_cb, VOS_FALSE );
2457#endif
2458
2459 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2460
2461 EXIT();
2462 return halStatus;
2463}
2464
2465tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2466{
2467 int i;
2468 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2469 {
2470 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2471 break;
2472 }
2473
2474 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2475 return NULL;
2476
2477 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2478 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2479}
2480
2481void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
2482{
2483 int i;
2484 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2485 {
2486 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
2487 {
2488 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
2489 break;
2490 }
2491 }
2492 return;
2493}
2494
2495#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2496 static struct net_device_ops wlan_drv_ops = {
2497 .ndo_open = hdd_open,
2498 .ndo_stop = hdd_stop,
2499 .ndo_uninit = hdd_uninit,
2500 .ndo_start_xmit = hdd_hard_start_xmit,
2501 .ndo_tx_timeout = hdd_tx_timeout,
2502 .ndo_get_stats = hdd_stats,
2503 .ndo_do_ioctl = hdd_ioctl,
2504 .ndo_set_mac_address = hdd_set_mac_address,
2505 .ndo_select_queue = hdd_select_queue,
2506#ifdef WLAN_FEATURE_PACKET_FILTERING
2507#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
2508 .ndo_set_rx_mode = hdd_set_multicast_list,
2509#else
2510 .ndo_set_multicast_list = hdd_set_multicast_list,
2511#endif //LINUX_VERSION_CODE
2512#endif
2513 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002514 static struct net_device_ops wlan_mon_drv_ops = {
2515 .ndo_open = hdd_mon_open,
2516 .ndo_stop = hdd_stop,
2517 .ndo_uninit = hdd_uninit,
2518 .ndo_start_xmit = hdd_mon_hard_start_xmit,
2519 .ndo_tx_timeout = hdd_tx_timeout,
2520 .ndo_get_stats = hdd_stats,
2521 .ndo_do_ioctl = hdd_ioctl,
2522 .ndo_set_mac_address = hdd_set_mac_address,
2523 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002524
2525#endif
2526
2527void hdd_set_station_ops( struct net_device *pWlanDev )
2528{
2529#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2530 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
2531 pWlanDev->netdev_ops = &wlan_drv_ops;
2532#else
2533 pWlanDev->open = hdd_open;
2534 pWlanDev->stop = hdd_stop;
2535 pWlanDev->uninit = hdd_uninit;
2536 pWlanDev->hard_start_xmit = NULL;
2537 pWlanDev->tx_timeout = hdd_tx_timeout;
2538 pWlanDev->get_stats = hdd_stats;
2539 pWlanDev->do_ioctl = hdd_ioctl;
2540 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
2541 pWlanDev->set_mac_address = hdd_set_mac_address;
2542#endif
2543}
2544
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002545static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07002546{
2547 struct net_device *pWlanDev = NULL;
2548 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002549 /*
2550 * cfg80211 initialization and registration....
2551 */
2552 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
2553
Jeff Johnson295189b2012-06-20 16:38:30 -07002554 if(pWlanDev != NULL)
2555 {
2556
2557 //Save the pointer to the net_device in the HDD adapter
2558 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
2559
Jeff Johnson295189b2012-06-20 16:38:30 -07002560 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
2561
2562 pAdapter->dev = pWlanDev;
2563 pAdapter->pHddCtx = pHddCtx;
2564 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
2565
2566 init_completion(&pAdapter->session_open_comp_var);
2567 init_completion(&pAdapter->session_close_comp_var);
2568 init_completion(&pAdapter->disconnect_comp_var);
2569 init_completion(&pAdapter->linkup_event_var);
2570 init_completion(&pAdapter->cancel_rem_on_chan_var);
2571 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07002572#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2573 init_completion(&pAdapter->offchannel_tx_event);
2574#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002575 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002576#ifdef FEATURE_WLAN_TDLS
2577 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002578 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002579 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002580#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002581 init_completion(&pHddCtx->mc_sus_event_var);
2582 init_completion(&pHddCtx->tx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07002583 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07002584
Jeff Johnson295189b2012-06-20 16:38:30 -07002585 pAdapter->isLinkUpSvcNeeded = FALSE;
2586 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
2587 //Init the net_device structure
2588 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2589
2590 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
2591 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
2592 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
2593 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
2594
2595 hdd_set_station_ops( pAdapter->dev );
2596
2597 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002598 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
2599 pAdapter->wdev.wiphy = pHddCtx->wiphy;
2600 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002601 /* set pWlanDev's parent to underlying device */
2602 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
2603 }
2604
2605 return pAdapter;
2606}
2607
2608VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
2609{
2610 struct net_device *pWlanDev = pAdapter->dev;
2611 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2612 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2613 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2614
2615 if( rtnl_lock_held )
2616 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08002617 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07002618 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
2619 {
2620 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
2621 return VOS_STATUS_E_FAILURE;
2622 }
2623 }
2624 if (register_netdevice(pWlanDev))
2625 {
2626 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
2627 return VOS_STATUS_E_FAILURE;
2628 }
2629 }
2630 else
2631 {
2632 if(register_netdev(pWlanDev))
2633 {
2634 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
2635 return VOS_STATUS_E_FAILURE;
2636 }
2637 }
2638 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
2639
2640 return VOS_STATUS_SUCCESS;
2641}
2642
2643eHalStatus hdd_smeCloseSessionCallback(void *pContext)
2644{
2645 if(pContext != NULL)
2646 {
2647 clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags);
2648
2649 /* need to make sure all of our scheduled work has completed.
2650 * This callback is called from MC thread context, so it is safe to
2651 * to call below flush workqueue API from here.
2652 */
2653 flush_scheduled_work();
2654 complete(&((hdd_adapter_t*)pContext)->session_close_comp_var);
2655 }
2656 return eHAL_STATUS_SUCCESS;
2657}
2658
2659VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
2660{
2661 struct net_device *pWlanDev = pAdapter->dev;
2662 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2663 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2664 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2665 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2666 int rc = 0;
2667
2668 INIT_COMPLETION(pAdapter->session_open_comp_var);
2669 //Open a SME session for future operation
2670 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
2671 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
2672 if ( !HAL_STATUS_SUCCESS( halStatus ) )
2673 {
2674 hddLog(VOS_TRACE_LEVEL_FATAL,
2675 "sme_OpenSession() failed with status code %08d [x%08lx]",
2676 halStatus, halStatus );
2677 status = VOS_STATUS_E_FAILURE;
2678 goto error_sme_open;
2679 }
2680
2681 //Block on a completion variable. Can't wait forever though.
2682 rc = wait_for_completion_interruptible_timeout(
2683 &pAdapter->session_open_comp_var,
2684 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2685 if (!rc)
2686 {
2687 hddLog(VOS_TRACE_LEVEL_FATAL,
2688 "Session is not opened within timeout period code %08d", rc );
2689 status = VOS_STATUS_E_FAILURE;
2690 goto error_sme_open;
2691 }
2692
2693 // Register wireless extensions
2694 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
2695 {
2696 hddLog(VOS_TRACE_LEVEL_FATAL,
2697 "hdd_register_wext() failed with status code %08d [x%08lx]",
2698 halStatus, halStatus );
2699 status = VOS_STATUS_E_FAILURE;
2700 goto error_register_wext;
2701 }
2702 //Safe to register the hard_start_xmit function again
2703#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2704 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
2705#else
2706 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
2707#endif
2708
2709 //Set the Connection State to Not Connected
2710 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2711
2712 //Set the default operation channel
2713 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
2714
2715 /* Make the default Auth Type as OPEN*/
2716 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2717
2718 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
2719 {
2720 hddLog(VOS_TRACE_LEVEL_FATAL,
2721 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
2722 status, status );
2723 goto error_init_txrx;
2724 }
2725
2726 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2727
2728 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
2729 {
2730 hddLog(VOS_TRACE_LEVEL_FATAL,
2731 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
2732 status, status );
2733 goto error_wmm_init;
2734 }
2735
2736 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2737
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002738#ifdef FEATURE_WLAN_TDLS
2739 if(0 != wlan_hdd_tdls_init(pAdapter))
2740 {
2741 status = VOS_STATUS_E_FAILURE;
2742 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
2743 goto error_tdls_init;
2744 }
2745 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2746#endif
2747
Jeff Johnson295189b2012-06-20 16:38:30 -07002748 return VOS_STATUS_SUCCESS;
2749
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002750#ifdef FEATURE_WLAN_TDLS
2751error_tdls_init:
2752 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2753 hdd_wmm_adapter_close(pAdapter);
2754#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002755error_wmm_init:
2756 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2757 hdd_deinit_tx_rx(pAdapter);
2758error_init_txrx:
2759 hdd_UnregisterWext(pWlanDev);
2760error_register_wext:
2761 if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
2762 {
2763 INIT_COMPLETION(pAdapter->session_close_comp_var);
2764 if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
2765 pAdapter->sessionId,
2766 hdd_smeCloseSessionCallback, pAdapter ) )
2767 {
2768 //Block on a completion variable. Can't wait forever though.
2769 wait_for_completion_interruptible_timeout(
2770 &pAdapter->session_close_comp_var,
2771 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2772 }
2773}
2774error_sme_open:
2775 return status;
2776}
2777
Jeff Johnson295189b2012-06-20 16:38:30 -07002778void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2779{
2780 hdd_cfg80211_state_t *cfgState;
2781
2782 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
2783
2784 if( NULL != cfgState->buf )
2785 {
2786 int rc;
2787 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
2788 rc = wait_for_completion_interruptible_timeout(
2789 &pAdapter->tx_action_cnf_event,
2790 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2791 if(!rc)
2792 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08002793 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07002794 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
2795 }
2796 }
2797 return;
2798}
Jeff Johnson295189b2012-06-20 16:38:30 -07002799
2800void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2801{
2802 ENTER();
2803 switch ( pAdapter->device_mode )
2804 {
2805 case WLAN_HDD_INFRA_STATION:
2806 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002807 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002808 {
2809 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2810 {
2811 hdd_deinit_tx_rx( pAdapter );
2812 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2813 }
2814
2815 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
2816 {
2817 hdd_wmm_adapter_close( pAdapter );
2818 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2819 }
2820
Jeff Johnson295189b2012-06-20 16:38:30 -07002821 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002822#ifdef FEATURE_WLAN_TDLS
2823 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
2824 {
2825 wlan_hdd_tdls_exit(pAdapter);
2826 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2827 }
2828#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002829
2830 break;
2831 }
2832
2833 case WLAN_HDD_SOFTAP:
2834 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002835 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002836 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002837
2838 hdd_unregister_hostapd(pAdapter);
2839 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07002840 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07002841 break;
2842 }
2843
2844 case WLAN_HDD_MONITOR:
2845 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002846 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07002847 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2848 {
2849 hdd_deinit_tx_rx( pAdapter );
2850 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2851 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002852 if(NULL != pAdapterforTx)
2853 {
2854 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
2855 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002856 break;
2857 }
2858
2859
2860 default:
2861 break;
2862 }
2863
2864 EXIT();
2865}
2866
2867void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
2868{
2869 struct net_device *pWlanDev = pAdapter->dev;
2870
2871 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
2872 if( rtnl_held )
2873 {
2874 unregister_netdevice(pWlanDev);
2875 }
2876 else
2877 {
2878 unregister_netdev(pWlanDev);
2879 }
2880 // note that the pAdapter is no longer valid at this point
2881 // since the memory has been reclaimed
2882 }
2883
2884}
2885
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08002886void hdd_set_pwrparams(hdd_context_t *pHddCtx)
2887{
2888 tSirSetPowerParamsReq powerRequest = { 0 };
2889
2890 powerRequest.uIgnoreDTIM = 1;
2891
2892 if (pHddCtx->cfg_ini->enableModulatedDTIM)
2893 {
2894 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
2895 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2896 }
2897 else
2898 {
2899 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
2900 }
2901
2902 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
2903 *specified during Enter/Exit BMPS when LCD off*/
2904 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2905 NULL, eANI_BOOLEAN_FALSE);
2906 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2907 NULL, eANI_BOOLEAN_FALSE);
2908
2909 /* switch to the DTIM specified in cfg.ini */
2910 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2911 "Switch to DTIM%d", powerRequest.uListenInterval);
2912 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2913
2914}
2915
2916void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
2917{
2918 /*Switch back to DTIM 1*/
2919 tSirSetPowerParamsReq powerRequest = { 0 };
2920
2921 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
2922 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2923
2924 /* Update ignoreDTIM and ListedInterval in CFG with default values */
2925 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2926 NULL, eANI_BOOLEAN_FALSE);
2927 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2928 NULL, eANI_BOOLEAN_FALSE);
2929
2930 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2931 "Switch to DTIM%d",powerRequest.uListenInterval);
2932 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2933
2934}
2935
Jeff Johnson295189b2012-06-20 16:38:30 -07002936VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
2937{
2938 VOS_STATUS status = VOS_STATUS_SUCCESS;
2939
2940 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2941 {
2942 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2943 }
2944
2945 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2946 {
2947 sme_StartAutoBmpsTimer(pHddCtx->hHal);
2948 }
2949
2950 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2951 {
2952 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2953 }
2954
2955 return status;
2956}
2957
2958VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
2959{
2960 hdd_adapter_t *pAdapter = NULL;
2961 eHalStatus halStatus;
2962 VOS_STATUS status = VOS_STATUS_E_INVAL;
2963 v_BOOL_t disableBmps = FALSE;
2964 v_BOOL_t disableImps = FALSE;
2965
2966 switch(session_type)
2967 {
2968 case WLAN_HDD_INFRA_STATION:
2969 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002970 case WLAN_HDD_P2P_CLIENT:
2971 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002972 //Exit BMPS -> Is Sta/P2P Client is already connected
2973 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
2974 if((NULL != pAdapter)&&
2975 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2976 {
2977 disableBmps = TRUE;
2978 }
2979
2980 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
2981 if((NULL != pAdapter)&&
2982 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2983 {
2984 disableBmps = TRUE;
2985 }
2986
2987 //Exit both Bmps and Imps incase of Go/SAP Mode
2988 if((WLAN_HDD_SOFTAP == session_type) ||
2989 (WLAN_HDD_P2P_GO == session_type))
2990 {
2991 disableBmps = TRUE;
2992 disableImps = TRUE;
2993 }
2994
2995 if(TRUE == disableImps)
2996 {
2997 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2998 {
2999 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3000 }
3001 }
3002
3003 if(TRUE == disableBmps)
3004 {
3005 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3006 {
3007 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3008
3009 if(eHAL_STATUS_SUCCESS != halStatus)
3010 {
3011 status = VOS_STATUS_E_FAILURE;
3012 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3013 VOS_ASSERT(0);
3014 return status;
3015 }
3016 }
3017
3018 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3019 {
3020 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3021
3022 if(eHAL_STATUS_SUCCESS != halStatus)
3023 {
3024 status = VOS_STATUS_E_FAILURE;
3025 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3026 VOS_ASSERT(0);
3027 return status;
3028 }
3029 }
3030 }
3031
3032 if((TRUE == disableBmps) ||
3033 (TRUE == disableImps))
3034 {
3035 /* Now, get the chip into Full Power now */
3036 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3037 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3038 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3039
3040 if(halStatus != eHAL_STATUS_SUCCESS)
3041 {
3042 if(halStatus == eHAL_STATUS_PMC_PENDING)
3043 {
3044 //Block on a completion variable. Can't wait forever though
3045 wait_for_completion_interruptible_timeout(
3046 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3047 }
3048 else
3049 {
3050 status = VOS_STATUS_E_FAILURE;
3051 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3052 VOS_ASSERT(0);
3053 return status;
3054 }
3055 }
3056
3057 status = VOS_STATUS_SUCCESS;
3058 }
3059
3060 break;
3061 }
3062 return status;
3063}
3064
3065hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003066 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003067 tANI_U8 rtnl_held )
3068{
3069 hdd_adapter_t *pAdapter = NULL;
3070 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3071 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3072 VOS_STATUS exitbmpsStatus;
3073
3074 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3075
3076 //Disable BMPS incase of Concurrency
3077 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3078
3079 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3080 {
3081 //Fail to Exit BMPS
3082 VOS_ASSERT(0);
3083 return NULL;
3084 }
3085
3086 switch(session_type)
3087 {
3088 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003089 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003090 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003091 {
3092 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3093
3094 if( NULL == pAdapter )
3095 return NULL;
3096
Jeff Johnsone7245742012-09-05 17:12:55 -07003097 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3098 NL80211_IFTYPE_P2P_CLIENT:
3099 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003100
Jeff Johnson295189b2012-06-20 16:38:30 -07003101 pAdapter->device_mode = session_type;
3102
3103 status = hdd_init_station_mode( pAdapter );
3104 if( VOS_STATUS_SUCCESS != status )
3105 goto err_free_netdev;
3106
3107 status = hdd_register_interface( pAdapter, rtnl_held );
3108 if( VOS_STATUS_SUCCESS != status )
3109 {
3110 hdd_deinit_adapter(pHddCtx, pAdapter);
3111 goto err_free_netdev;
3112 }
3113 //Stop the Interface TX queue.
3114 netif_tx_disable(pAdapter->dev);
3115 //netif_tx_disable(pWlanDev);
3116 netif_carrier_off(pAdapter->dev);
3117
3118 break;
3119 }
3120
Jeff Johnson295189b2012-06-20 16:38:30 -07003121 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003122 case WLAN_HDD_SOFTAP:
3123 {
3124 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3125 if( NULL == pAdapter )
3126 return NULL;
3127
Jeff Johnson295189b2012-06-20 16:38:30 -07003128 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3129 NL80211_IFTYPE_AP:
3130 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003131 pAdapter->device_mode = session_type;
3132
3133 status = hdd_init_ap_mode(pAdapter);
3134 if( VOS_STATUS_SUCCESS != status )
3135 goto err_free_netdev;
3136
3137 status = hdd_register_hostapd( pAdapter, rtnl_held );
3138 if( VOS_STATUS_SUCCESS != status )
3139 {
3140 hdd_deinit_adapter(pHddCtx, pAdapter);
3141 goto err_free_netdev;
3142 }
3143
3144 netif_tx_disable(pAdapter->dev);
3145 netif_carrier_off(pAdapter->dev);
3146
3147 hdd_set_conparam( 1 );
3148 break;
3149 }
3150 case WLAN_HDD_MONITOR:
3151 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003152 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3153 if( NULL == pAdapter )
3154 return NULL;
3155
3156 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3157 pAdapter->device_mode = session_type;
3158 status = hdd_register_interface( pAdapter, rtnl_held );
3159#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3160 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3161#else
3162 pAdapter->dev->open = hdd_mon_open;
3163 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3164#endif
3165 hdd_init_tx_rx( pAdapter );
3166 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3167 //Set adapter to be used for data tx. It will use either GO or softap.
3168 pAdapter->sessionCtx.monitor.pAdapterForTx =
3169 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003170 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3171 {
3172 pAdapter->sessionCtx.monitor.pAdapterForTx =
3173 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3174 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003175 /* This workqueue will be used to transmit management packet over
3176 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003177 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3178 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3179 return NULL;
3180 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003181
Jeff Johnson295189b2012-06-20 16:38:30 -07003182 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3183 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003184 }
3185 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003186 case WLAN_HDD_FTM:
3187 {
3188 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3189
3190 if( NULL == pAdapter )
3191 return NULL;
3192 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3193 * message while loading driver in FTM mode. */
3194 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3195 pAdapter->device_mode = session_type;
3196 status = hdd_register_interface( pAdapter, rtnl_held );
3197 }
3198 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003199 default:
3200 {
3201 VOS_ASSERT(0);
3202 return NULL;
3203 }
3204 }
3205
3206
3207 if( VOS_STATUS_SUCCESS == status )
3208 {
3209 //Add it to the hdd's session list.
3210 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3211 if( NULL == pHddAdapterNode )
3212 {
3213 status = VOS_STATUS_E_NOMEM;
3214 }
3215 else
3216 {
3217 pHddAdapterNode->pAdapter = pAdapter;
3218 status = hdd_add_adapter_back ( pHddCtx,
3219 pHddAdapterNode );
3220 }
3221 }
3222
3223 if( VOS_STATUS_SUCCESS != status )
3224 {
3225 if( NULL != pAdapter )
3226 {
3227 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3228 pAdapter = NULL;
3229 }
3230 if( NULL != pHddAdapterNode )
3231 {
3232 vos_mem_free( pHddAdapterNode );
3233 }
3234
3235 goto resume_bmps;
3236 }
3237
3238 if(VOS_STATUS_SUCCESS == status)
3239 {
3240 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3241
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003242 //Initialize the WoWL service
3243 if(!hdd_init_wowl(pAdapter))
3244 {
3245 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3246 goto err_free_netdev;
3247 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003248 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003249 return pAdapter;
3250
3251err_free_netdev:
3252 free_netdev(pAdapter->dev);
3253 wlan_hdd_release_intf_addr( pHddCtx,
3254 pAdapter->macAddressCurrent.bytes );
3255
3256resume_bmps:
3257 //If bmps disabled enable it
3258 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3259 {
3260 hdd_enable_bmps_imps(pHddCtx);
3261 }
3262 return NULL;
3263}
3264
3265VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3266 tANI_U8 rtnl_held )
3267{
3268 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3269 VOS_STATUS status;
3270
3271 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3272 if( VOS_STATUS_SUCCESS != status )
3273 return status;
3274
3275 while ( pCurrent->pAdapter != pAdapter )
3276 {
3277 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3278 if( VOS_STATUS_SUCCESS != status )
3279 break;
3280
3281 pCurrent = pNext;
3282 }
3283 pAdapterNode = pCurrent;
3284 if( VOS_STATUS_SUCCESS == status )
3285 {
3286 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3287 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3288 hdd_remove_adapter( pHddCtx, pAdapterNode );
3289 vos_mem_free( pAdapterNode );
3290
Jeff Johnson295189b2012-06-20 16:38:30 -07003291
3292 /* If there is a single session of STA/P2P client, re-enable BMPS */
3293 if ((!vos_concurrent_sessions_running()) &&
3294 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3295 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3296 {
3297 hdd_enable_bmps_imps(pHddCtx);
3298 }
3299
3300 return VOS_STATUS_SUCCESS;
3301 }
3302
3303 return VOS_STATUS_E_FAILURE;
3304}
3305
3306VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3307{
3308 hdd_adapter_list_node_t *pHddAdapterNode;
3309 VOS_STATUS status;
3310
3311 ENTER();
3312
3313 do
3314 {
3315 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3316 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3317 {
3318 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3319 vos_mem_free( pHddAdapterNode );
3320 }
3321 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3322
3323 EXIT();
3324
3325 return VOS_STATUS_SUCCESS;
3326}
3327
3328void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3329{
3330 v_U8_t addIE[1] = {0};
3331
3332 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3333 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3334 eANI_BOOLEAN_FALSE) )
3335 {
3336 hddLog(LOGE,
3337 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3338 }
3339
3340 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3341 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3342 eANI_BOOLEAN_FALSE) )
3343 {
3344 hddLog(LOGE,
3345 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3346 }
3347
3348 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3349 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3350 eANI_BOOLEAN_FALSE) )
3351 {
3352 hddLog(LOGE,
3353 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3354 }
3355}
3356
3357VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3358{
3359 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3360 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3361 union iwreq_data wrqu;
3362
3363 ENTER();
3364
3365 switch(pAdapter->device_mode)
3366 {
3367 case WLAN_HDD_INFRA_STATION:
3368 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003369 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003370 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3371 {
3372 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3373 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3374 pAdapter->sessionId,
3375 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3376 else
3377 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3378 pAdapter->sessionId,
3379 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3380 //success implies disconnect command got queued up successfully
3381 if(halStatus == eHAL_STATUS_SUCCESS)
3382 {
3383 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3384 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3385 }
3386 memset(&wrqu, '\0', sizeof(wrqu));
3387 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3388 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3389 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3390 }
3391 else
3392 {
3393 hdd_abort_mac_scan(pHddCtx);
3394 }
3395
3396 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3397 {
3398 INIT_COMPLETION(pAdapter->session_close_comp_var);
3399 if (eHAL_STATUS_SUCCESS ==
3400 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3401 hdd_smeCloseSessionCallback, pAdapter))
3402 {
3403 //Block on a completion variable. Can't wait forever though.
3404 wait_for_completion_interruptible_timeout(
3405 &pAdapter->session_close_comp_var,
3406 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3407 }
3408 }
3409
3410 break;
3411
3412 case WLAN_HDD_SOFTAP:
3413 case WLAN_HDD_P2P_GO:
3414 //Any softap specific cleanup here...
3415 mutex_lock(&pHddCtx->sap_lock);
3416 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3417 {
3418 VOS_STATUS status;
3419 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3420
3421 //Stop Bss.
3422 status = WLANSAP_StopBss(pHddCtx->pvosContext);
3423 if (VOS_IS_STATUS_SUCCESS(status))
3424 {
3425 hdd_hostapd_state_t *pHostapdState =
3426 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3427
3428 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
3429
3430 if (!VOS_IS_STATUS_SUCCESS(status))
3431 {
3432 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003433 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003434 }
3435 }
3436 else
3437 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003438 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003439 }
3440 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
3441
3442 if (eHAL_STATUS_FAILURE ==
3443 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
3444 0, NULL, eANI_BOOLEAN_FALSE))
3445 {
3446 hddLog(LOGE,
3447 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003448 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003449 }
3450
3451 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
3452 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
3453 eANI_BOOLEAN_FALSE) )
3454 {
3455 hddLog(LOGE,
3456 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
3457 }
3458
3459 // Reset WNI_CFG_PROBE_RSP Flags
3460 wlan_hdd_reset_prob_rspies(pAdapter);
3461 kfree(pAdapter->sessionCtx.ap.beacon);
3462 pAdapter->sessionCtx.ap.beacon = NULL;
3463 }
3464 mutex_unlock(&pHddCtx->sap_lock);
3465 break;
3466 case WLAN_HDD_MONITOR:
3467 break;
3468 default:
3469 break;
3470 }
3471
3472 EXIT();
3473 return VOS_STATUS_SUCCESS;
3474}
3475
3476VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
3477{
3478 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3479 VOS_STATUS status;
3480 hdd_adapter_t *pAdapter;
3481
3482 ENTER();
3483
3484 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3485
3486 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3487 {
3488 pAdapter = pAdapterNode->pAdapter;
3489 netif_tx_disable(pAdapter->dev);
3490 netif_carrier_off(pAdapter->dev);
3491
3492 hdd_stop_adapter( pHddCtx, pAdapter );
3493
3494 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3495 pAdapterNode = pNext;
3496 }
3497
3498 EXIT();
3499
3500 return VOS_STATUS_SUCCESS;
3501}
3502
3503VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
3504{
3505 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3506 VOS_STATUS status;
3507 hdd_adapter_t *pAdapter;
3508
3509 ENTER();
3510
3511 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3512
3513 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3514 {
3515 pAdapter = pAdapterNode->pAdapter;
3516 netif_tx_disable(pAdapter->dev);
3517 netif_carrier_off(pAdapter->dev);
3518
3519 //Record whether STA is associated
3520 pAdapter->sessionCtx.station.bSendDisconnect =
3521 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
3522 VOS_TRUE : VOS_FALSE;
3523
3524 hdd_deinit_tx_rx(pAdapter);
3525 hdd_wmm_adapter_close(pAdapter);
3526
3527 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3528 pAdapterNode = pNext;
3529 }
3530
3531 EXIT();
3532
3533 return VOS_STATUS_SUCCESS;
3534}
3535
3536VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
3537{
3538 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3539 VOS_STATUS status;
3540 hdd_adapter_t *pAdapter;
3541 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
3542
3543 ENTER();
3544
3545 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3546
3547 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3548 {
3549 pAdapter = pAdapterNode->pAdapter;
3550
3551 switch(pAdapter->device_mode)
3552 {
3553 case WLAN_HDD_INFRA_STATION:
3554 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003555 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003556 hdd_init_station_mode(pAdapter);
3557 /* Open the gates for HDD to receive Wext commands */
3558 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003559 pHddCtx->scan_info.mScanPending = FALSE;
3560 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003561
3562 //Trigger the initial scan
3563 hdd_wlan_initial_scan(pAdapter);
3564
3565 //Indicate disconnect event to supplicant if associated previously
3566 if(pAdapter->sessionCtx.station.bSendDisconnect)
3567 {
3568 union iwreq_data wrqu;
3569 memset(&wrqu, '\0', sizeof(wrqu));
3570 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3571 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3572 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3573 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
3574
Jeff Johnson295189b2012-06-20 16:38:30 -07003575 /* indicate disconnected event to nl80211 */
3576 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
3577 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003578 }
3579 break;
3580
3581 case WLAN_HDD_SOFTAP:
3582 /* softAP can handle SSR */
3583 break;
3584
3585 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003586 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
3587 __func__);
3588 /* event supplicant to restart */
3589 cfg80211_del_sta(pAdapter->dev,
3590 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003591 break;
3592
3593 case WLAN_HDD_MONITOR:
3594 /* monitor interface start */
3595 break;
3596 default:
3597 break;
3598 }
3599
3600 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3601 pAdapterNode = pNext;
3602 }
3603
3604 EXIT();
3605
3606 return VOS_STATUS_SUCCESS;
3607}
3608
3609VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
3610{
3611 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3612 hdd_adapter_t *pAdapter;
3613 VOS_STATUS status;
3614 v_U32_t roamId;
3615
3616 ENTER();
3617
3618 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3619
3620 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3621 {
3622 pAdapter = pAdapterNode->pAdapter;
3623
3624 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3625 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
3626 {
3627 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3628 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3629
3630 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3631 init_completion(&pAdapter->disconnect_comp_var);
3632 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
3633 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3634
3635 wait_for_completion_interruptible_timeout(
3636 &pAdapter->disconnect_comp_var,
3637 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3638
3639 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
3640 pHddCtx->isAmpAllowed = VOS_FALSE;
3641 sme_RoamConnect(pHddCtx->hHal,
3642 pAdapter->sessionId, &(pWextState->roamProfile),
3643 &roamId);
3644 }
3645
3646 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3647 pAdapterNode = pNext;
3648 }
3649
3650 EXIT();
3651
3652 return VOS_STATUS_SUCCESS;
3653}
3654
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07003655void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
3656{
3657 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3658 VOS_STATUS status;
3659 hdd_adapter_t *pAdapter;
3660 hdd_station_ctx_t *pHddStaCtx;
3661 hdd_ap_ctx_t *pHddApCtx;
3662 hdd_hostapd_state_t * pHostapdState;
3663 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
3664 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
3665 const char *p2pMode = "DEV";
3666 const char *ccMode = "Standalone";
3667 int n;
3668
3669 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3670 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3671 {
3672 pAdapter = pAdapterNode->pAdapter;
3673 switch (pAdapter->device_mode) {
3674 case WLAN_HDD_INFRA_STATION:
3675 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3676 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3677 staChannel = pHddStaCtx->conn_info.operationChannel;
3678 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
3679 }
3680 break;
3681 case WLAN_HDD_P2P_CLIENT:
3682 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3683 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3684 p2pChannel = pHddStaCtx->conn_info.operationChannel;
3685 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
3686 p2pMode = "CLI";
3687 }
3688 break;
3689 case WLAN_HDD_P2P_GO:
3690 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3691 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3692 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3693 p2pChannel = pHddApCtx->operatingChannel;
3694 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
3695 }
3696 p2pMode = "GO";
3697 break;
3698 case WLAN_HDD_SOFTAP:
3699 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3700 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3701 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3702 apChannel = pHddApCtx->operatingChannel;
3703 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
3704 }
3705 break;
3706 default:
3707 break;
3708 }
3709 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3710 pAdapterNode = pNext;
3711 }
3712 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
3713 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
3714 }
3715 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
3716 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
3717 if (p2pChannel > 0) {
3718 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
3719 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
3720 }
3721 if (apChannel > 0) {
3722 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
3723 apChannel, MAC_ADDR_ARRAY(apBssid));
3724 }
3725
3726 if (p2pChannel > 0 && apChannel > 0) {
3727 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
3728 }
3729}
3730
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003731bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07003732{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003733 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07003734}
3735
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003736/* Once SSR is disabled then it cannot be set. */
3737void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07003738{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003739 if (HDD_SSR_DISABLED == isSsrRequired)
3740 return;
3741
Jeff Johnson295189b2012-06-20 16:38:30 -07003742 isSsrRequired = value;
3743}
3744
3745VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
3746 hdd_adapter_list_node_t** ppAdapterNode)
3747{
3748 VOS_STATUS status;
3749 spin_lock(&pHddCtx->hddAdapters.lock);
3750 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
3751 (hdd_list_node_t**) ppAdapterNode );
3752 spin_unlock(&pHddCtx->hddAdapters.lock);
3753 return status;
3754}
3755
3756VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
3757 hdd_adapter_list_node_t* pAdapterNode,
3758 hdd_adapter_list_node_t** pNextAdapterNode)
3759{
3760 VOS_STATUS status;
3761 spin_lock(&pHddCtx->hddAdapters.lock);
3762 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
3763 (hdd_list_node_t*) pAdapterNode,
3764 (hdd_list_node_t**)pNextAdapterNode );
3765
3766 spin_unlock(&pHddCtx->hddAdapters.lock);
3767 return status;
3768}
3769
3770VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
3771 hdd_adapter_list_node_t* pAdapterNode)
3772{
3773 VOS_STATUS status;
3774 spin_lock(&pHddCtx->hddAdapters.lock);
3775 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
3776 &pAdapterNode->node );
3777 spin_unlock(&pHddCtx->hddAdapters.lock);
3778 return status;
3779}
3780
3781VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
3782 hdd_adapter_list_node_t** ppAdapterNode)
3783{
3784 VOS_STATUS status;
3785 spin_lock(&pHddCtx->hddAdapters.lock);
3786 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
3787 (hdd_list_node_t**) ppAdapterNode );
3788 spin_unlock(&pHddCtx->hddAdapters.lock);
3789 return status;
3790}
3791
3792VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
3793 hdd_adapter_list_node_t* pAdapterNode)
3794{
3795 VOS_STATUS status;
3796 spin_lock(&pHddCtx->hddAdapters.lock);
3797 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
3798 (hdd_list_node_t*) pAdapterNode );
3799 spin_unlock(&pHddCtx->hddAdapters.lock);
3800 return status;
3801}
3802
3803VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
3804 hdd_adapter_list_node_t* pAdapterNode)
3805{
3806 VOS_STATUS status;
3807 spin_lock(&pHddCtx->hddAdapters.lock);
3808 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
3809 (hdd_list_node_t*) pAdapterNode );
3810 spin_unlock(&pHddCtx->hddAdapters.lock);
3811 return status;
3812}
3813
3814hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
3815 tSirMacAddr macAddr )
3816{
3817 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3818 hdd_adapter_t *pAdapter;
3819 VOS_STATUS status;
3820
3821 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3822
3823 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3824 {
3825 pAdapter = pAdapterNode->pAdapter;
3826
3827 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
3828 macAddr, sizeof(tSirMacAddr) ) )
3829 {
3830 return pAdapter;
3831 }
3832 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3833 pAdapterNode = pNext;
3834 }
3835
3836 return NULL;
3837
3838}
3839
3840hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
3841{
3842 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3843 hdd_adapter_t *pAdapter;
3844 VOS_STATUS status;
3845
3846 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3847
3848 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3849 {
3850 pAdapter = pAdapterNode->pAdapter;
3851
3852 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
3853 IFNAMSIZ ) )
3854 {
3855 return pAdapter;
3856 }
3857 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3858 pAdapterNode = pNext;
3859 }
3860
3861 return NULL;
3862
3863}
3864
3865hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
3866{
3867 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3868 hdd_adapter_t *pAdapter;
3869 VOS_STATUS status;
3870
3871 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3872
3873 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3874 {
3875 pAdapter = pAdapterNode->pAdapter;
3876
3877 if( pAdapter && (mode == pAdapter->device_mode) )
3878 {
3879 return pAdapter;
3880 }
3881 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3882 pAdapterNode = pNext;
3883 }
3884
3885 return NULL;
3886
3887}
3888
3889//Remove this function later
3890hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
3891{
3892 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3893 hdd_adapter_t *pAdapter;
3894 VOS_STATUS status;
3895
3896 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3897
3898 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3899 {
3900 pAdapter = pAdapterNode->pAdapter;
3901
3902 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
3903 {
3904 return pAdapter;
3905 }
3906
3907 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3908 pAdapterNode = pNext;
3909 }
3910
3911 return NULL;
3912
3913}
3914
Jeff Johnson295189b2012-06-20 16:38:30 -07003915/**---------------------------------------------------------------------------
3916
3917 \brief hdd_set_monitor_tx_adapter() -
3918
3919 This API initializes the adapter to be used while transmitting on monitor
3920 adapter.
3921
3922 \param - pHddCtx - Pointer to the HDD context.
3923 pAdapter - Adapter that will used for TX. This can be NULL.
3924 \return - None.
3925 --------------------------------------------------------------------------*/
3926void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3927{
3928 hdd_adapter_t *pMonAdapter;
3929
3930 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
3931
3932 if( NULL != pMonAdapter )
3933 {
3934 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
3935 }
3936}
Jeff Johnson295189b2012-06-20 16:38:30 -07003937/**---------------------------------------------------------------------------
3938
3939 \brief hdd_select_queue() -
3940
3941 This API returns the operating channel of the requested device mode
3942
3943 \param - pHddCtx - Pointer to the HDD context.
3944 - mode - Device mode for which operating channel is required
3945 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
3946 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
3947 \return - channel number. "0" id the requested device is not found OR it is not connected.
3948 --------------------------------------------------------------------------*/
3949v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
3950{
3951 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3952 VOS_STATUS status;
3953 hdd_adapter_t *pAdapter;
3954 v_U8_t operatingChannel = 0;
3955
3956 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3957
3958 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3959 {
3960 pAdapter = pAdapterNode->pAdapter;
3961
3962 if( mode == pAdapter->device_mode )
3963 {
3964 switch(pAdapter->device_mode)
3965 {
3966 case WLAN_HDD_INFRA_STATION:
3967 case WLAN_HDD_P2P_CLIENT:
3968 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3969 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
3970 break;
3971 case WLAN_HDD_SOFTAP:
3972 case WLAN_HDD_P2P_GO:
3973 /*softap connection info */
3974 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3975 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
3976 break;
3977 default:
3978 break;
3979 }
3980
3981 break; //Found the device of interest. break the loop
3982 }
3983
3984 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3985 pAdapterNode = pNext;
3986 }
3987 return operatingChannel;
3988}
3989
3990#ifdef WLAN_FEATURE_PACKET_FILTERING
3991/**---------------------------------------------------------------------------
3992
3993 \brief hdd_set_multicast_list() -
3994
3995 This used to set the multicast address list.
3996
3997 \param - dev - Pointer to the WLAN device.
3998 - skb - Pointer to OS packet (sk_buff).
3999 \return - success/fail
4000
4001 --------------------------------------------------------------------------*/
4002static void hdd_set_multicast_list(struct net_device *dev)
4003{
4004 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004005 int mc_count;
4006 int i = 0;
4007 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304008
4009 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004010 {
4011 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304012 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004013 return;
4014 }
4015
4016 if (dev->flags & IFF_ALLMULTI)
4017 {
4018 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004019 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304020 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004021 }
4022 else
4023 {
4024 mc_count = netdev_mc_count(dev);
4025 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004026 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004027 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4028 {
4029 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004030 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304031 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004032 return;
4033 }
4034
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304035 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004036
4037 netdev_for_each_mc_addr(ha, dev) {
4038 if (i == mc_count)
4039 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304040 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4041 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4042 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004043 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304044 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004045 i++;
4046 }
4047 }
4048 return;
4049}
4050#endif
4051
4052/**---------------------------------------------------------------------------
4053
4054 \brief hdd_select_queue() -
4055
4056 This function is registered with the Linux OS for network
4057 core to decide which queue to use first.
4058
4059 \param - dev - Pointer to the WLAN device.
4060 - skb - Pointer to OS packet (sk_buff).
4061 \return - ac, Queue Index/access category corresponding to UP in IP header
4062
4063 --------------------------------------------------------------------------*/
4064v_U16_t hdd_select_queue(struct net_device *dev,
4065 struct sk_buff *skb)
4066{
4067 return hdd_wmm_select_queue(dev, skb);
4068}
4069
4070
4071/**---------------------------------------------------------------------------
4072
4073 \brief hdd_wlan_initial_scan() -
4074
4075 This function triggers the initial scan
4076
4077 \param - pAdapter - Pointer to the HDD adapter.
4078
4079 --------------------------------------------------------------------------*/
4080void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4081{
4082 tCsrScanRequest scanReq;
4083 tCsrChannelInfo channelInfo;
4084 eHalStatus halStatus;
4085 unsigned long scanId;
4086 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4087
4088 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4089 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4090 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4091
4092 if(sme_Is11dSupported(pHddCtx->hHal))
4093 {
4094 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4095 if ( HAL_STATUS_SUCCESS( halStatus ) )
4096 {
4097 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4098 if( !scanReq.ChannelInfo.ChannelList )
4099 {
4100 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4101 vos_mem_free(channelInfo.ChannelList);
4102 return;
4103 }
4104 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4105 channelInfo.numOfChannels);
4106 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4107 vos_mem_free(channelInfo.ChannelList);
4108 }
4109
4110 scanReq.scanType = eSIR_PASSIVE_SCAN;
4111 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4112 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4113 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4114 }
4115 else
4116 {
4117 scanReq.scanType = eSIR_ACTIVE_SCAN;
4118 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4119 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4120 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4121 }
4122
4123 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4124 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4125 {
4126 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4127 __func__, halStatus );
4128 }
4129
4130 if(sme_Is11dSupported(pHddCtx->hHal))
4131 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4132}
4133
4134struct fullPowerContext
4135{
4136 struct completion completion;
4137 unsigned int magic;
4138};
4139#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4140
4141/**---------------------------------------------------------------------------
4142
4143 \brief hdd_full_power_callback() - HDD full power callback function
4144
4145 This is the function invoked by SME to inform the result of a full power
4146 request issued by HDD
4147
4148 \param - callbackcontext - Pointer to cookie
4149 \param - status - result of request
4150
4151 \return - None
4152
4153 --------------------------------------------------------------------------*/
4154static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4155{
4156 struct fullPowerContext *pContext = callbackContext;
4157
4158 hddLog(VOS_TRACE_LEVEL_INFO,
4159 "%s: context = %p, status = %d", pContext, status);
4160
4161 if (NULL == callbackContext)
4162 {
4163 hddLog(VOS_TRACE_LEVEL_ERROR,
4164 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004165 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004166 return;
4167 }
4168
4169 /* there is a race condition that exists between this callback function
4170 and the caller since the caller could time out either before or
4171 while this code is executing. we'll assume the timeout hasn't
4172 occurred, but we'll verify that right before we save our work */
4173
4174 if (POWER_CONTEXT_MAGIC != pContext->magic)
4175 {
4176 /* the caller presumably timed out so there is nothing we can do */
4177 hddLog(VOS_TRACE_LEVEL_WARN,
4178 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004179 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004180 return;
4181 }
4182
4183 /* the race is on. caller could have timed out immediately after
4184 we verified the magic, but if so, caller will wait a short time
4185 for us to notify the caller, so the context will stay valid */
4186 complete(&pContext->completion);
4187}
4188
4189/**---------------------------------------------------------------------------
4190
4191 \brief hdd_wlan_exit() - HDD WLAN exit function
4192
4193 This is the driver exit point (invoked during rmmod)
4194
4195 \param - pHddCtx - Pointer to the HDD Context
4196
4197 \return - None
4198
4199 --------------------------------------------------------------------------*/
4200void hdd_wlan_exit(hdd_context_t *pHddCtx)
4201{
4202 eHalStatus halStatus;
4203 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4204 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304205 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004206 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004207 struct fullPowerContext powerContext;
4208 long lrc;
4209
4210 ENTER();
4211
Jeff Johnson88ba7742013-02-27 14:36:02 -08004212 if (VOS_FTM_MODE != hdd_get_conparam())
4213 {
4214 // Unloading, restart logic is no more required.
4215 wlan_hdd_restart_deinit(pHddCtx);
4216 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004217
Jeff Johnson295189b2012-06-20 16:38:30 -07004218 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004219 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004220 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004221 {
4222 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4223 WLAN_HDD_INFRA_STATION);
4224 if (pAdapter == NULL)
4225 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4226
4227 if (pAdapter != NULL)
4228 {
4229 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4230 hdd_UnregisterWext(pAdapter->dev);
4231 }
4232 }
4233 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004234
Jeff Johnson295189b2012-06-20 16:38:30 -07004235 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004236 {
4237 wlan_hdd_ftm_close(pHddCtx);
4238 goto free_hdd_ctx;
4239 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004240 //Stop the Interface TX queue.
4241 //netif_tx_disable(pWlanDev);
4242 //netif_carrier_off(pWlanDev);
4243
Jeff Johnson295189b2012-06-20 16:38:30 -07004244 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4245 {
4246 pAdapter = hdd_get_adapter(pHddCtx,
4247 WLAN_HDD_SOFTAP);
4248 }
4249 else
4250 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004251 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004252 {
4253 pAdapter = hdd_get_adapter(pHddCtx,
4254 WLAN_HDD_INFRA_STATION);
4255 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004256 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004257 /* DeRegister with platform driver as client for Suspend/Resume */
4258 vosStatus = hddDeregisterPmOps(pHddCtx);
4259 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4260 {
4261 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4262 VOS_ASSERT(0);
4263 }
4264
4265 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4266 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4267 {
4268 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4269 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004270
4271 // Cancel any outstanding scan requests. We are about to close all
4272 // of our adapters, but an adapter structure is what SME passes back
4273 // to our callback function. Hence if there are any outstanding scan
4274 // requests then there is a race condition between when the adapter
4275 // is closed and when the callback is invoked. We try to resolve that
4276 // race condition here by canceling any outstanding scans before we
4277 // close the adapters.
4278 // Note that the scans may be cancelled in an asynchronous manner, so
4279 // ideally there needs to be some kind of synchronization. Rather than
4280 // introduce a new synchronization here, we will utilize the fact that
4281 // we are about to Request Full Power, and since that is synchronized,
4282 // the expectation is that by the time Request Full Power has completed,
4283 // all scans will be cancelled.
4284 hdd_abort_mac_scan( pHddCtx );
4285
4286 //Disable IMPS/BMPS as we do not want the device to enter any power
4287 //save mode during shutdown
4288 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4289 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4290 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4291
4292 //Ensure that device is in full power as we will touch H/W during vos_Stop
4293 init_completion(&powerContext.completion);
4294 powerContext.magic = POWER_CONTEXT_MAGIC;
4295
4296 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4297 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4298
4299 if (eHAL_STATUS_SUCCESS != halStatus)
4300 {
4301 if (eHAL_STATUS_PMC_PENDING == halStatus)
4302 {
4303 /* request was sent -- wait for the response */
4304 lrc = wait_for_completion_interruptible_timeout(
4305 &powerContext.completion,
4306 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4307 /* either we have a response or we timed out
4308 either way, first invalidate our magic */
4309 powerContext.magic = 0;
4310 if (lrc <= 0)
4311 {
4312 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004313 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004314 /* there is a race condition such that the callback
4315 function could be executing at the same time we are. of
4316 primary concern is if the callback function had already
4317 verified the "magic" but hasn't yet set the completion
4318 variable. Since the completion variable is on our
4319 stack, we'll delay just a bit to make sure the data is
4320 still valid if that is the case */
4321 msleep(50);
4322 }
4323 }
4324 else
4325 {
4326 hddLog(VOS_TRACE_LEVEL_ERROR,
4327 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004328 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004329 VOS_ASSERT(0);
4330 /* continue -- need to clean up as much as possible */
4331 }
4332 }
4333
4334 // Unregister the Net Device Notifier
4335 unregister_netdevice_notifier(&hdd_netdev_notifier);
4336
Jeff Johnson295189b2012-06-20 16:38:30 -07004337 hdd_stop_all_adapters( pHddCtx );
4338
Jeff Johnson295189b2012-06-20 16:38:30 -07004339#ifdef WLAN_BTAMP_FEATURE
4340 vosStatus = WLANBAP_Stop(pVosContext);
4341 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4342 {
4343 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4344 "%s: Failed to stop BAP",__func__);
4345 }
4346#endif //WLAN_BTAMP_FEATURE
4347
4348 //Stop all the modules
4349 vosStatus = vos_stop( pVosContext );
4350 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4351 {
4352 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4353 "%s: Failed to stop VOSS",__func__);
4354 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4355 }
4356
Jeff Johnson295189b2012-06-20 16:38:30 -07004357 //Assert Deep sleep signal now to put Libra HW in lowest power state
4358 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4359 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4360
4361 //Vote off any PMIC voltage supplies
4362 vos_chipPowerDown(NULL, NULL, NULL);
4363
4364 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4365
4366 //Clean up HDD Nlink Service
4367 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
4368 nl_srv_exit();
4369
4370 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004371 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004372
4373 //Close the scheduler before calling vos_close to make sure no thread is
4374 // scheduled after the each module close is called i.e after all the data
4375 // structures are freed.
4376 vosStatus = vos_sched_close( pVosContext );
4377 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4378 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4379 "%s: Failed to close VOSS Scheduler",__func__);
4380 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4381 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004382#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004383#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4384 /* Destroy the wake lock */
4385 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4386#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004387 /* Destroy the wake lock */
4388 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004389#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004390
4391 //Close VOSS
4392 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4393 vos_close(pVosContext);
4394
Jeff Johnson295189b2012-06-20 16:38:30 -07004395 //Close Watchdog
4396 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4397 vos_watchdog_close(pVosContext);
4398
4399 /* Cancel the vote for XO Core ON.
4400 * This is done here to ensure there is no race condition since MC, TX and WD threads have
4401 * exited at this point
4402 */
4403 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
4404 " when WLAN is turned OFF\n");
4405 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4406 {
4407 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
4408 " Not returning failure."
4409 " Power consumed will be high\n");
4410 }
4411
4412 hdd_close_all_adapters( pHddCtx );
4413
4414
4415 //Free up dynamically allocated members inside HDD Adapter
4416 kfree(pHddCtx->cfg_ini);
4417 pHddCtx->cfg_ini= NULL;
4418
4419 /* free the power on lock from platform driver */
4420 if (free_riva_power_on_lock("wlan"))
4421 {
4422 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
4423 __func__);
4424 }
4425
Jeff Johnson88ba7742013-02-27 14:36:02 -08004426free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08004427 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004428 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004429 if (hdd_is_ssr_required())
4430 {
4431 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07004432 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07004433 msleep(5000);
4434 }
4435 hdd_set_ssr_required (VOS_FALSE);
4436}
4437
4438
4439/**---------------------------------------------------------------------------
4440
4441 \brief hdd_update_config_from_nv() - Function to update the contents of
4442 the running configuration with parameters taken from NV storage
4443
4444 \param - pHddCtx - Pointer to the HDD global context
4445
4446 \return - VOS_STATUS_SUCCESS if successful
4447
4448 --------------------------------------------------------------------------*/
4449static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
4450{
Jeff Johnson295189b2012-06-20 16:38:30 -07004451 v_BOOL_t itemIsValid = VOS_FALSE;
4452 VOS_STATUS status;
4453 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
4454 v_U8_t macLoop;
4455
4456 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
4457 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
4458 if(status != VOS_STATUS_SUCCESS)
4459 {
4460 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
4461 return VOS_STATUS_E_FAILURE;
4462 }
4463
4464 if (itemIsValid == VOS_TRUE)
4465 {
4466 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
4467 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
4468 VOS_MAX_CONCURRENCY_PERSONA);
4469 if(status != VOS_STATUS_SUCCESS)
4470 {
4471 /* Get MAC from NV fail, not update CFG info
4472 * INI MAC value will be used for MAC setting */
4473 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
4474 return VOS_STATUS_E_FAILURE;
4475 }
4476
4477 /* If first MAC is not valid, treat all others are not valid
4478 * Then all MACs will be got from ini file */
4479 if(vos_is_macaddr_zero(&macFromNV[0]))
4480 {
4481 /* MAC address in NV file is not configured yet */
4482 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
4483 return VOS_STATUS_E_INVAL;
4484 }
4485
4486 /* Get MAC address from NV, update CFG info */
4487 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
4488 {
4489 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
4490 {
4491 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
4492 /* This MAC is not valid, skip it
4493 * This MAC will be got from ini file */
4494 }
4495 else
4496 {
4497 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
4498 (v_U8_t *)&macFromNV[macLoop].bytes[0],
4499 VOS_MAC_ADDR_SIZE);
4500 }
4501 }
4502 }
4503 else
4504 {
4505 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
4506 return VOS_STATUS_E_FAILURE;
4507 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004508
Jeff Johnson295189b2012-06-20 16:38:30 -07004509
4510 return VOS_STATUS_SUCCESS;
4511}
4512
4513/**---------------------------------------------------------------------------
4514
4515 \brief hdd_post_voss_start_config() - HDD post voss start config helper
4516
4517 \param - pAdapter - Pointer to the HDD
4518
4519 \return - None
4520
4521 --------------------------------------------------------------------------*/
4522VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
4523{
4524 eHalStatus halStatus;
4525 v_U32_t listenInterval;
4526
Jeff Johnson295189b2012-06-20 16:38:30 -07004527
4528 // Send ready indication to the HDD. This will kick off the MAC
4529 // into a 'running' state and should kick off an initial scan.
4530 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
4531 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4532 {
4533 hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
4534 "code %08d [x%08x]",__func__, halStatus, halStatus );
4535 return VOS_STATUS_E_FAILURE;
4536 }
4537
4538 // Set default LI into HDD context,
4539 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
4540 // And RIVA will crash
4541 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
4542 pHddCtx->hdd_actual_LI_value = listenInterval;
4543
4544 return VOS_STATUS_SUCCESS;
4545}
4546
Jeff Johnson295189b2012-06-20 16:38:30 -07004547/* wake lock APIs for HDD */
4548void hdd_prevent_suspend(void)
4549{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004550#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004551 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004552#else
4553 wcnss_prevent_suspend();
4554#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004555}
4556
4557void hdd_allow_suspend(void)
4558{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004559#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004560 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004561#else
4562 wcnss_allow_suspend();
4563#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004564}
4565
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004566void hdd_allow_suspend_timeout(v_U32_t timeout)
4567{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004568#ifdef WLAN_OPEN_SOURCE
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004569 wake_lock_timeout(&wlan_wake_lock, timeout);
4570#else
4571 /* Do nothing as there is no API in wcnss for timeout*/
4572#endif
4573}
4574
Jeff Johnson295189b2012-06-20 16:38:30 -07004575/**---------------------------------------------------------------------------
4576
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004577 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
4578 information between Host and Riva
4579
4580 This function gets reported version of FW
4581 It also finds the version of Riva headers used to compile the host
4582 It compares the above two and prints a warning if they are different
4583 It gets the SW and HW version string
4584 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
4585 indicating the features they support through a bitmap
4586
4587 \param - pHddCtx - Pointer to HDD context
4588
4589 \return - void
4590
4591 --------------------------------------------------------------------------*/
4592
4593void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
4594{
4595
4596 tSirVersionType versionCompiled;
4597 tSirVersionType versionReported;
4598 tSirVersionString versionString;
4599 tANI_U8 fwFeatCapsMsgSupported = 0;
4600 VOS_STATUS vstatus;
4601
4602 /* retrieve and display WCNSS version information */
4603 do {
4604
4605 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
4606 &versionCompiled);
4607 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4608 {
4609 hddLog(VOS_TRACE_LEVEL_FATAL,
4610 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004611 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004612 break;
4613 }
4614
4615 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
4616 &versionReported);
4617 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4618 {
4619 hddLog(VOS_TRACE_LEVEL_FATAL,
4620 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004621 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004622 break;
4623 }
4624
4625 if ((versionCompiled.major != versionReported.major) ||
4626 (versionCompiled.minor != versionReported.minor) ||
4627 (versionCompiled.version != versionReported.version) ||
4628 (versionCompiled.revision != versionReported.revision))
4629 {
4630 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4631 "Host expected %u.%u.%u.%u\n",
4632 WLAN_MODULE_NAME,
4633 (int)versionReported.major,
4634 (int)versionReported.minor,
4635 (int)versionReported.version,
4636 (int)versionReported.revision,
4637 (int)versionCompiled.major,
4638 (int)versionCompiled.minor,
4639 (int)versionCompiled.version,
4640 (int)versionCompiled.revision);
4641 }
4642 else
4643 {
4644 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4645 WLAN_MODULE_NAME,
4646 (int)versionReported.major,
4647 (int)versionReported.minor,
4648 (int)versionReported.version,
4649 (int)versionReported.revision);
4650 }
4651
4652 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
4653 versionString,
4654 sizeof(versionString));
4655 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4656 {
4657 hddLog(VOS_TRACE_LEVEL_FATAL,
4658 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004659 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004660 break;
4661 }
4662
4663 pr_info("%s: WCNSS software version %s\n",
4664 WLAN_MODULE_NAME, versionString);
4665
4666 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
4667 versionString,
4668 sizeof(versionString));
4669 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4670 {
4671 hddLog(VOS_TRACE_LEVEL_FATAL,
4672 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004673 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004674 break;
4675 }
4676
4677 pr_info("%s: WCNSS hardware version %s\n",
4678 WLAN_MODULE_NAME, versionString);
4679
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004680 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
4681 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004682 send the message only if it the riva is 1.1
4683 minor numbers for different riva branches:
4684 0 -> (1.0)Mainline Build
4685 1 -> (1.1)Mainline Build
4686 2->(1.04) Stability Build
4687 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004688 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004689 ((versionReported.minor>=1) && (versionReported.version>=1)))
4690 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
4691 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004692
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004693 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08004694 {
4695#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4696 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
4697 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
4698#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004699 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08004700 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004701
4702 } while (0);
4703
4704}
4705
4706/**---------------------------------------------------------------------------
4707
Jeff Johnson295189b2012-06-20 16:38:30 -07004708 \brief hdd_wlan_startup() - HDD init function
4709
4710 This is the driver startup code executed once a WLAN device has been detected
4711
4712 \param - dev - Pointer to the underlying device
4713
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004714 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07004715
4716 --------------------------------------------------------------------------*/
4717
4718int hdd_wlan_startup(struct device *dev )
4719{
4720 VOS_STATUS status;
4721 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004722 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004723 hdd_context_t *pHddCtx = NULL;
4724 v_CONTEXT_t pVosContext= NULL;
4725#ifdef WLAN_BTAMP_FEATURE
4726 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
4727 WLANBAP_ConfigType btAmpConfig;
4728 hdd_config_t *pConfig;
4729#endif
4730 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07004731 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004732
4733 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07004734 /*
4735 * cfg80211: wiphy allocation
4736 */
4737 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
4738
4739 if(wiphy == NULL)
4740 {
4741 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004742 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004743 }
4744
4745 pHddCtx = wiphy_priv(wiphy);
4746
Jeff Johnson295189b2012-06-20 16:38:30 -07004747 //Initialize the adapter context to zeros.
4748 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
4749
Jeff Johnson295189b2012-06-20 16:38:30 -07004750 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004751 hdd_prevent_suspend();
4752 pHddCtx->isLoadUnloadInProgress = TRUE;
4753
4754 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4755
4756 /*Get vos context here bcoz vos_open requires it*/
4757 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4758
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08004759 if(pVosContext == NULL)
4760 {
4761 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
4762 goto err_free_hdd_context;
4763 }
4764
Jeff Johnson295189b2012-06-20 16:38:30 -07004765 //Save the Global VOSS context in adapter context for future.
4766 pHddCtx->pvosContext = pVosContext;
4767
4768 //Save the adapter context in global context for future.
4769 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
4770
Jeff Johnson295189b2012-06-20 16:38:30 -07004771 pHddCtx->parent_dev = dev;
4772
4773 init_completion(&pHddCtx->full_pwr_comp_var);
4774 init_completion(&pHddCtx->standby_comp_var);
4775 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004776 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004777 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004778
4779 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
4780
4781 // Load all config first as TL config is needed during vos_open
4782 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
4783 if(pHddCtx->cfg_ini == NULL)
4784 {
4785 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
4786 goto err_free_hdd_context;
4787 }
4788
4789 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
4790
4791 // Read and parse the qcom_cfg.ini file
4792 status = hdd_parse_config_ini( pHddCtx );
4793 if ( VOS_STATUS_SUCCESS != status )
4794 {
4795 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
4796 __func__, WLAN_INI_FILE);
4797 goto err_config;
4798 }
4799
Jeff Johnson295189b2012-06-20 16:38:30 -07004800 /*
4801 * cfg80211: Initialization and registration ...
4802 */
4803 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
4804 {
4805 hddLog(VOS_TRACE_LEVEL_FATAL,
4806 "%s: wlan_hdd_cfg80211_register return failure", __func__);
4807 goto err_wiphy_reg;
4808 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004809
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004810 // Update VOS trace levels based upon the cfg.ini
4811 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
4812 pHddCtx->cfg_ini->vosTraceEnableBAP);
4813 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
4814 pHddCtx->cfg_ini->vosTraceEnableTL);
4815 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
4816 pHddCtx->cfg_ini->vosTraceEnableWDI);
4817 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
4818 pHddCtx->cfg_ini->vosTraceEnableHDD);
4819 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
4820 pHddCtx->cfg_ini->vosTraceEnableSME);
4821 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
4822 pHddCtx->cfg_ini->vosTraceEnablePE);
4823 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
4824 pHddCtx->cfg_ini->vosTraceEnableWDA);
4825 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
4826 pHddCtx->cfg_ini->vosTraceEnableSYS);
4827 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
4828 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004829 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
4830 pHddCtx->cfg_ini->vosTraceEnableSAP);
4831 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
4832 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004833
Jeff Johnson295189b2012-06-20 16:38:30 -07004834 // Update WDI trace levels based upon the cfg.ini
4835 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
4836 pHddCtx->cfg_ini->wdiTraceEnableDAL);
4837 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
4838 pHddCtx->cfg_ini->wdiTraceEnableCTL);
4839 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
4840 pHddCtx->cfg_ini->wdiTraceEnableDAT);
4841 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
4842 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004843
Jeff Johnson88ba7742013-02-27 14:36:02 -08004844 if (VOS_FTM_MODE == hdd_get_conparam())
4845 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004846 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
4847 {
4848 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
4849 goto err_free_hdd_context;
4850 }
4851 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
4852 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08004853 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004854
Jeff Johnson88ba7742013-02-27 14:36:02 -08004855 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07004856 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4857 {
4858 status = vos_watchdog_open(pVosContext,
4859 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
4860
4861 if(!VOS_IS_STATUS_SUCCESS( status ))
4862 {
4863 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004864 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07004865 }
4866 }
4867
4868 pHddCtx->isLogpInProgress = FALSE;
4869 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4870
Jeff Johnson295189b2012-06-20 16:38:30 -07004871 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
4872 if(!VOS_IS_STATUS_SUCCESS(status))
4873 {
4874 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004875 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004876 }
4877
Jeff Johnson295189b2012-06-20 16:38:30 -07004878 status = vos_open( &pVosContext, 0);
4879 if ( !VOS_IS_STATUS_SUCCESS( status ))
4880 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004881 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
4882 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07004883 }
4884
Jeff Johnson295189b2012-06-20 16:38:30 -07004885 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
4886
4887 if ( NULL == pHddCtx->hHal )
4888 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004889 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004890 goto err_vosclose;
4891 }
4892
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004893 status = vos_preStart( pHddCtx->pvosContext );
4894 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4895 {
4896 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
4897 goto err_vosclose;
4898 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004899
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004900 /* Note that the vos_preStart() sequence triggers the cfg download.
4901 The cfg download must occur before we update the SME config
4902 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07004903 status = hdd_set_sme_config( pHddCtx );
4904
4905 if ( VOS_STATUS_SUCCESS != status )
4906 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004907 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
4908 goto err_vosclose;
4909 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004910
4911 //Initialize the WMM module
4912 status = hdd_wmm_init(pHddCtx);
4913 if (!VOS_IS_STATUS_SUCCESS(status))
4914 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004915 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004916 goto err_vosclose;
4917 }
4918
Jeff Johnson295189b2012-06-20 16:38:30 -07004919 /* In the integrated architecture we update the configuration from
4920 the INI file and from NV before vOSS has been started so that
4921 the final contents are available to send down to the cCPU */
4922
4923 // Apply the cfg.ini to cfg.dat
4924 if (FALSE == hdd_update_config_dat(pHddCtx))
4925 {
4926 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
4927 goto err_vosclose;
4928 }
4929
4930 // Apply the NV to cfg.dat
4931 /* Prima Update MAC address only at here */
4932 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
4933 {
4934#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
4935 /* There was not a valid set of MAC Addresses in NV. See if the
4936 default addresses were modified by the cfg.ini settings. If so,
4937 we'll use them, but if not, we'll autogenerate a set of MAC
4938 addresses based upon the device serial number */
4939
4940 static const v_MACADDR_t default_address =
4941 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
4942 unsigned int serialno;
4943 int i;
4944
4945 serialno = wcnss_get_serial_number();
4946 if ((0 != serialno) &&
4947 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
4948 sizeof(default_address))))
4949 {
4950 /* cfg.ini has the default address, invoke autogen logic */
4951
4952 /* MAC address has 3 bytes of OUI so we have a maximum of 3
4953 bytes of the serial number that can be used to generate
4954 the other 3 bytes of the MAC address. Mask off all but
4955 the lower 3 bytes (this will also make sure we don't
4956 overflow in the next step) */
4957 serialno &= 0x00FFFFFF;
4958
4959 /* we need a unique address for each session */
4960 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
4961
4962 /* autogen all addresses */
4963 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4964 {
4965 /* start with the entire default address */
4966 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
4967 /* then replace the lower 3 bytes */
4968 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
4969 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
4970 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
4971
4972 serialno++;
4973 }
4974
4975 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
4976 MAC_ADDRESS_STR,
4977 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4978 }
4979 else
4980#endif //WLAN_AUTOGEN_MACADDR_FEATURE
4981 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004982 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004983 "%s: Invalid MAC address in NV, using MAC from ini file "
4984 MAC_ADDRESS_STR, __func__,
4985 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4986 }
4987 }
4988 {
4989 eHalStatus halStatus;
4990 // Set the MAC Address
4991 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
4992 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
4993 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
4994 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
4995
4996 if (!HAL_STATUS_SUCCESS( halStatus ))
4997 {
4998 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
4999 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005000 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005001 }
5002 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005003
5004 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5005 Note: Firmware image will be read and downloaded inside vos_start API */
5006 status = vos_start( pHddCtx->pvosContext );
5007 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5008 {
5009 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5010 goto err_vosclose;
5011 }
5012
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005013 /* Exchange capability info between Host and FW and also get versioning info from FW */
5014 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005015
5016 status = hdd_post_voss_start_config( pHddCtx );
5017 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5018 {
5019 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5020 __func__);
5021 goto err_vosstop;
5022 }
5023
Jeff Johnson295189b2012-06-20 16:38:30 -07005024 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5025 {
5026 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5027 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5028 }
5029 else
5030 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005031 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5032 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5033 if (pAdapter != NULL)
5034 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305035 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005036 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305037 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5038 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5039 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005040
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305041 /* Generate the P2P Device Address. This consists of the device's
5042 * primary MAC address with the locally administered bit set.
5043 */
5044 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005045 }
5046 else
5047 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305048 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5049 if (p2p_dev_addr != NULL)
5050 {
5051 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5052 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5053 }
5054 else
5055 {
5056 hddLog(VOS_TRACE_LEVEL_FATAL,
5057 "%s: Failed to allocate mac_address for p2p_device",
5058 __func__);
5059 goto err_close_adapter;
5060 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005061 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005062
5063 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5064 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5065 if ( NULL == pP2pAdapter )
5066 {
5067 hddLog(VOS_TRACE_LEVEL_FATAL,
5068 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005069 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005070 goto err_close_adapter;
5071 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005072 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005073 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005074
5075 if( pAdapter == NULL )
5076 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005077 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5078 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005079 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005080
Jeff Johnson295189b2012-06-20 16:38:30 -07005081#ifdef WLAN_BTAMP_FEATURE
5082 vStatus = WLANBAP_Open(pVosContext);
5083 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5084 {
5085 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5086 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005087 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005088 }
5089
5090 vStatus = BSL_Init(pVosContext);
5091 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5092 {
5093 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5094 "%s: Failed to Init BSL",__func__);
5095 goto err_bap_close;
5096 }
5097 vStatus = WLANBAP_Start(pVosContext);
5098 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5099 {
5100 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5101 "%s: Failed to start TL",__func__);
5102 goto err_bap_close;
5103 }
5104
5105 pConfig = pHddCtx->cfg_ini;
5106 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5107 status = WLANBAP_SetConfig(&btAmpConfig);
5108
5109#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005110
Jeff Johnson295189b2012-06-20 16:38:30 -07005111#ifdef FEATURE_WLAN_SCAN_PNO
5112 /*SME must send channel update configuration to RIVA*/
5113 sme_UpdateChannelConfig(pHddCtx->hHal);
5114#endif
5115
Jeff Johnson295189b2012-06-20 16:38:30 -07005116 /* Register with platform driver as client for Suspend/Resume */
5117 status = hddRegisterPmOps(pHddCtx);
5118 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5119 {
5120 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5121#ifdef WLAN_BTAMP_FEATURE
5122 goto err_bap_stop;
5123#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005124 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005125#endif //WLAN_BTAMP_FEATURE
5126 }
5127
5128 /* Register TM level change handler function to the platform */
5129 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5130 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5131 {
5132 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5133 goto err_unregister_pmops;
5134 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005135
5136 /* register for riva power on lock to platform driver */
5137 if (req_riva_power_on_lock("wlan"))
5138 {
5139 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5140 __func__);
5141 goto err_unregister_pmops;
5142 }
5143
Jeff Johnson295189b2012-06-20 16:38:30 -07005144 // register net device notifier for device change notification
5145 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5146
5147 if(ret < 0)
5148 {
5149 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5150 goto err_free_power_on_lock;
5151 }
5152
5153 //Initialize the nlink service
5154 if(nl_srv_init() != 0)
5155 {
5156 hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
5157 goto err_reg_netdev;
5158 }
5159
5160 //Initialize the BTC service
5161 if(btc_activate_service(pHddCtx) != 0)
5162 {
5163 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5164 goto err_nl_srv;
5165 }
5166
5167#ifdef PTT_SOCK_SVC_ENABLE
5168 //Initialize the PTT service
5169 if(ptt_sock_activate_svc(pHddCtx) != 0)
5170 {
5171 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5172 goto err_nl_srv;
5173 }
5174#endif
5175
Jeff Johnson295189b2012-06-20 16:38:30 -07005176 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005177 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005178 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005179 /* Action frame registered in one adapter which will
5180 * applicable to all interfaces
5181 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005182 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005183 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005184
5185 mutex_init(&pHddCtx->sap_lock);
5186
5187 pHddCtx->isLoadUnloadInProgress = FALSE;
5188
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005189#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005190#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5191 /* Initialize the wake lcok */
5192 wake_lock_init(&pHddCtx->rx_wake_lock,
5193 WAKE_LOCK_SUSPEND,
5194 "qcom_rx_wakelock");
5195#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005196 /* Initialize the wake lcok */
5197 wake_lock_init(&pHddCtx->sap_wake_lock,
5198 WAKE_LOCK_SUSPEND,
5199 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005200#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005201
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005202 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5203 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005204
5205 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5206 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005207
5208 // Initialize the restart logic
5209 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305210
Jeff Johnson295189b2012-06-20 16:38:30 -07005211 goto success;
5212
5213err_nl_srv:
5214 nl_srv_exit();
5215
5216err_reg_netdev:
5217 unregister_netdevice_notifier(&hdd_netdev_notifier);
5218
5219err_free_power_on_lock:
5220 free_riva_power_on_lock("wlan");
5221
5222err_unregister_pmops:
5223 hddDevTmUnregisterNotifyCallback(pHddCtx);
5224 hddDeregisterPmOps(pHddCtx);
5225
5226#ifdef WLAN_BTAMP_FEATURE
5227err_bap_stop:
5228 WLANBAP_Stop(pVosContext);
5229#endif
5230
5231#ifdef WLAN_BTAMP_FEATURE
5232err_bap_close:
5233 WLANBAP_Close(pVosContext);
5234#endif
5235
Jeff Johnson295189b2012-06-20 16:38:30 -07005236err_close_adapter:
5237 hdd_close_all_adapters( pHddCtx );
5238
5239err_vosstop:
5240 vos_stop(pVosContext);
5241
5242err_vosclose:
5243 status = vos_sched_close( pVosContext );
5244 if (!VOS_IS_STATUS_SUCCESS(status)) {
5245 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5246 "%s: Failed to close VOSS Scheduler", __func__);
5247 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5248 }
5249 vos_close(pVosContext );
5250
Jeff Johnson295189b2012-06-20 16:38:30 -07005251err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005252 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005253
5254err_wdclose:
5255 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5256 vos_watchdog_close(pVosContext);
5257
Jeff Johnson295189b2012-06-20 16:38:30 -07005258err_wiphy_reg:
5259 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005260
5261err_config:
5262 kfree(pHddCtx->cfg_ini);
5263 pHddCtx->cfg_ini= NULL;
5264
5265err_free_hdd_context:
5266 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005267 wiphy_free(wiphy) ;
5268 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005269 VOS_BUG(1);
5270
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005271 if (hdd_is_ssr_required())
5272 {
5273 /* WDI timeout had happened during load, so SSR is needed here */
5274 subsystem_restart("wcnss");
5275 msleep(5000);
5276 }
5277 hdd_set_ssr_required (VOS_FALSE);
5278
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005279 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005280
5281success:
5282 EXIT();
5283 return 0;
5284}
5285
5286/**---------------------------------------------------------------------------
5287
Jeff Johnson32d95a32012-09-10 13:15:23 -07005288 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07005289
Jeff Johnson32d95a32012-09-10 13:15:23 -07005290 This is the driver entry point - called in different timeline depending
5291 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07005292
5293 \param - None
5294
5295 \return - 0 for success, non zero for failure
5296
5297 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07005298static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005299{
5300 VOS_STATUS status;
5301 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005302 struct device *dev = NULL;
5303 int ret_status = 0;
5304
5305 ENTER();
5306
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005307#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005308 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07005309#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005310
5311 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
5312 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
5313
5314 //Power Up Libra WLAN card first if not already powered up
5315 status = vos_chipPowerUp(NULL,NULL,NULL);
5316 if (!VOS_IS_STATUS_SUCCESS(status))
5317 {
5318 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
5319 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005320 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005321 }
5322
Jeff Johnson295189b2012-06-20 16:38:30 -07005323#ifdef ANI_BUS_TYPE_PCI
5324
5325 dev = wcnss_wlan_get_device();
5326
5327#endif // ANI_BUS_TYPE_PCI
5328
5329#ifdef ANI_BUS_TYPE_PLATFORM
5330 dev = wcnss_wlan_get_device();
5331#endif // ANI_BUS_TYPE_PLATFORM
5332
5333
5334 do {
5335 if (NULL == dev) {
5336 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
5337 ret_status = -1;
5338 break;
5339 }
5340
5341#ifdef MEMORY_DEBUG
5342 vos_mem_init();
5343#endif
5344
5345#ifdef TIMER_MANAGER
5346 vos_timer_manager_init();
5347#endif
5348
5349 /* Preopen VOSS so that it is ready to start at least SAL */
5350 status = vos_preOpen(&pVosContext);
5351
5352 if (!VOS_IS_STATUS_SUCCESS(status))
5353 {
5354 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
5355 ret_status = -1;
5356 break;
5357 }
5358
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005359#ifndef MODULE
5360 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
5361 */
5362 hdd_set_conparam((v_UINT_t)con_mode);
5363#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005364
5365 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005366 if (hdd_wlan_startup(dev))
5367 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005368 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005369 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005370 vos_preClose( &pVosContext );
5371 ret_status = -1;
5372 break;
5373 }
5374
5375 /* Cancel the vote for XO Core ON
5376 * This is done here for safety purposes in case we re-initialize without turning
5377 * it OFF in any error scenario.
5378 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005379 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07005380 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005381 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07005382 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5383 {
5384 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
5385 " Power consumed will be high\n");
5386 }
5387 } while (0);
5388
5389 if (0 != ret_status)
5390 {
5391 //Assert Deep sleep signal now to put Libra HW in lowest power state
5392 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5393 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
5394
5395 //Vote off any PMIC voltage supplies
5396 vos_chipPowerDown(NULL, NULL, NULL);
5397#ifdef TIMER_MANAGER
5398 vos_timer_exit();
5399#endif
5400#ifdef MEMORY_DEBUG
5401 vos_mem_exit();
5402#endif
5403
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005404#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005405 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005406#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005407 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
5408 }
5409 else
5410 {
5411 //Send WLAN UP indication to Nlink Service
5412 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
5413
5414 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
5415
5416 }
5417
5418 EXIT();
5419
5420 return ret_status;
5421}
5422
Jeff Johnson32d95a32012-09-10 13:15:23 -07005423/**---------------------------------------------------------------------------
5424
5425 \brief hdd_module_init() - Init Function
5426
5427 This is the driver entry point (invoked when module is loaded using insmod)
5428
5429 \param - None
5430
5431 \return - 0 for success, non zero for failure
5432
5433 --------------------------------------------------------------------------*/
5434#ifdef MODULE
5435static int __init hdd_module_init ( void)
5436{
5437 return hdd_driver_init();
5438}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005439#else /* #ifdef MODULE */
5440static int __init hdd_module_init ( void)
5441{
5442 /* Driver initialization is delayed to fwpath_changed_handler */
5443 return 0;
5444}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005445#endif /* #ifdef MODULE */
5446
Jeff Johnson295189b2012-06-20 16:38:30 -07005447
5448/**---------------------------------------------------------------------------
5449
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005450 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005451
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005452 This is the driver exit point (invoked when module is unloaded using rmmod
5453 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07005454
5455 \param - None
5456
5457 \return - None
5458
5459 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005460static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005461{
5462 hdd_context_t *pHddCtx = NULL;
5463 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005464
5465 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
5466
5467 //Get the global vos context
5468 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5469
5470 if(!pVosContext)
5471 {
5472 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
5473 goto done;
5474 }
5475
5476 //Get the HDD context.
5477 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
5478
5479 if(!pHddCtx)
5480 {
5481 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
5482 }
5483 else
5484 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005485 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07005486 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07005487 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
5488 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07005489 }
5490
5491 pHddCtx->isLoadUnloadInProgress = TRUE;
5492 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5493
5494 //Do all the cleanup before deregistering the driver
5495 hdd_wlan_exit(pHddCtx);
5496 }
5497
Jeff Johnson295189b2012-06-20 16:38:30 -07005498 vos_preClose( &pVosContext );
5499
5500#ifdef TIMER_MANAGER
5501 vos_timer_exit();
5502#endif
5503#ifdef MEMORY_DEBUG
5504 vos_mem_exit();
5505#endif
5506
5507done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005508#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005509 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005510#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005511 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
5512}
5513
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005514/**---------------------------------------------------------------------------
5515
5516 \brief hdd_module_exit() - Exit function
5517
5518 This is the driver exit point (invoked when module is unloaded using rmmod)
5519
5520 \param - None
5521
5522 \return - None
5523
5524 --------------------------------------------------------------------------*/
5525static void __exit hdd_module_exit(void)
5526{
5527 hdd_driver_exit();
5528}
5529
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005530#ifdef MODULE
5531static int fwpath_changed_handler(const char *kmessage,
5532 struct kernel_param *kp)
5533{
5534 /* nothing to do when driver is DLKM */
5535 return 0;
5536}
5537
5538static int con_mode_handler(const char *kmessage,
5539 struct kernel_param *kp)
5540{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07005541 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005542}
5543#else /* #ifdef MODULE */
5544/**---------------------------------------------------------------------------
5545
5546 \brief fwpath_changed_handler() - Handler Function
5547
5548 This is the driver entry point
5549 - delayed driver initialization when driver is statically linked
5550 - invoked when module parameter fwpath is modified from userpspace to signal
5551 initializing the WLAN driver
5552
5553 \return - 0 for success, non zero for failure
5554
5555 --------------------------------------------------------------------------*/
5556static int fwpath_changed_handler(const char *kmessage,
5557 struct kernel_param *kp)
5558{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005559 int ret_status;
5560
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005561 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005562 ret_status = hdd_driver_init();
5563 wlan_hdd_inited = ret_status ? 0 : 1;
5564 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005565 }
5566
5567 hdd_driver_exit();
5568
5569 msleep(200);
5570
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005571 ret_status = hdd_driver_init();
5572 wlan_hdd_inited = ret_status ? 0 : 1;
5573 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005574}
5575
Jeff Johnson295189b2012-06-20 16:38:30 -07005576/**---------------------------------------------------------------------------
5577
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005578 \brief con_mode_handler() -
5579
5580 Handler function for module param con_mode when it is changed by userspace
5581 Dynamically linked - do nothing
5582 Statically linked - exit and init driver, as in rmmod and insmod
5583
5584 \param -
5585
5586 \return -
5587
5588 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005589static int con_mode_handler(const char *kmessage,
5590 struct kernel_param *kp)
5591{
5592 int ret = param_set_int(kmessage, kp);
5593
5594 if (ret)
5595 return ret;
5596
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005597 return fwpath_changed_handler(kmessage, kp);
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005598}
5599#endif /* #ifdef MODULE */
5600
5601/**---------------------------------------------------------------------------
5602
Jeff Johnson295189b2012-06-20 16:38:30 -07005603 \brief hdd_get_conparam() -
5604
5605 This is the driver exit point (invoked when module is unloaded using rmmod)
5606
5607 \param - None
5608
5609 \return - tVOS_CON_MODE
5610
5611 --------------------------------------------------------------------------*/
5612tVOS_CON_MODE hdd_get_conparam ( void )
5613{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005614#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07005615 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005616#else
5617 return (tVOS_CON_MODE)curr_con_mode;
5618#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005619}
5620void hdd_set_conparam ( v_UINT_t newParam )
5621{
5622 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005623#ifndef MODULE
5624 curr_con_mode = con_mode;
5625#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005626}
5627/**---------------------------------------------------------------------------
5628
5629 \brief hdd_softap_sta_deauth() - function
5630
5631 This to take counter measure to handle deauth req from HDD
5632
5633 \param - pAdapter - Pointer to the HDD
5634
5635 \param - enable - boolean value
5636
5637 \return - None
5638
5639 --------------------------------------------------------------------------*/
5640
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005641VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07005642{
Jeff Johnson295189b2012-06-20 16:38:30 -07005643 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005644 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07005645
5646 ENTER();
5647
5648 hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5649
5650 //Ignore request to deauth bcmc station
5651 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005652 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005653
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005654 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07005655
5656 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005657 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005658}
5659
5660/**---------------------------------------------------------------------------
5661
5662 \brief hdd_softap_sta_disassoc() - function
5663
5664 This to take counter measure to handle deauth req from HDD
5665
5666 \param - pAdapter - Pointer to the HDD
5667
5668 \param - enable - boolean value
5669
5670 \return - None
5671
5672 --------------------------------------------------------------------------*/
5673
5674void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
5675{
5676 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5677
5678 ENTER();
5679
5680 hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5681
5682 //Ignore request to disassoc bcmc station
5683 if( pDestMacAddress[0] & 0x1 )
5684 return;
5685
5686 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
5687}
5688
5689void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
5690{
5691 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5692
5693 ENTER();
5694
5695 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5696
5697 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
5698}
5699
Jeff Johnson295189b2012-06-20 16:38:30 -07005700/**---------------------------------------------------------------------------
5701 *
5702 * \brief hdd_get__concurrency_mode() -
5703 *
5704 *
5705 * \param - None
5706 *
5707 * \return - CONCURRENCY MODE
5708 *
5709 * --------------------------------------------------------------------------*/
5710tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
5711{
5712 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5713 hdd_context_t *pHddCtx;
5714
5715 if (NULL != pVosContext)
5716 {
5717 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5718 if (NULL != pHddCtx)
5719 {
5720 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
5721 }
5722 }
5723
5724 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005725 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005726 return VOS_STA;
5727}
5728
5729/* Decide whether to allow/not the apps power collapse.
5730 * Allow apps power collapse if we are in connected state.
5731 * if not, allow only if we are in IMPS */
5732v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
5733{
5734 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08005735 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005736 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07005737 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5738 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5739 hdd_adapter_t *pAdapter = NULL;
5740 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08005741 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005742
Jeff Johnson295189b2012-06-20 16:38:30 -07005743 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5744 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005745
Yathish9f22e662012-12-10 14:21:35 -08005746 concurrent_state = hdd_get_concurrency_mode();
5747
5748#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5749 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
5750 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
5751 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
5752 return TRUE;
5753#endif
5754
Jeff Johnson295189b2012-06-20 16:38:30 -07005755 /*loop through all adapters. TBD fix for Concurrency */
5756 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5757 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5758 {
5759 pAdapter = pAdapterNode->pAdapter;
5760 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
5761 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5762 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005763 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07005764 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08005765 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005766 (eANI_BOOLEAN_TRUE == scanRspPending) ||
5767 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07005768 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005769 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005770 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
5771 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07005772 return FALSE;
5773 }
5774 }
5775 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5776 pAdapterNode = pNext;
5777 }
5778 return TRUE;
5779}
5780
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08005781/* Decides whether to send suspend notification to Riva
5782 * if any adapter is in BMPS; then it is required */
5783v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
5784{
5785 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
5786 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5787
5788 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
5789 {
5790 return TRUE;
5791 }
5792 return FALSE;
5793}
5794
Jeff Johnson295189b2012-06-20 16:38:30 -07005795void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5796{
5797 switch(mode)
5798 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005799 case VOS_STA_MODE:
5800 case VOS_P2P_CLIENT_MODE:
5801 case VOS_P2P_GO_MODE:
5802 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07005803 pHddCtx->concurrency_mode |= (1 << mode);
5804 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07005805 break;
5806 default:
5807 break;
5808
5809 }
5810 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5811 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5812}
5813
5814
5815void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5816{
5817 switch(mode)
5818 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005819 case VOS_STA_MODE:
5820 case VOS_P2P_CLIENT_MODE:
5821 case VOS_P2P_GO_MODE:
5822 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005823 pHddCtx->no_of_sessions[mode]--;
5824 if (!(pHddCtx->no_of_sessions[mode]))
5825 pHddCtx->concurrency_mode &= (~(1 << mode));
5826 break;
5827 default:
5828 break;
5829 }
5830 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5831 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5832}
5833
Jeff Johnsone7245742012-09-05 17:12:55 -07005834/**---------------------------------------------------------------------------
5835 *
5836 * \brief wlan_hdd_restart_init
5837 *
5838 * This function initalizes restart timer/flag. An internal function.
5839 *
5840 * \param - pHddCtx
5841 *
5842 * \return - None
5843 *
5844 * --------------------------------------------------------------------------*/
5845
5846static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
5847{
5848 /* Initialize */
5849 pHddCtx->hdd_restart_retries = 0;
5850 atomic_set(&pHddCtx->isRestartInProgress, 0);
5851 vos_timer_init(&pHddCtx->hdd_restart_timer,
5852 VOS_TIMER_TYPE_SW,
5853 wlan_hdd_restart_timer_cb,
5854 pHddCtx);
5855}
5856/**---------------------------------------------------------------------------
5857 *
5858 * \brief wlan_hdd_restart_deinit
5859 *
5860 * This function cleans up the resources used. An internal function.
5861 *
5862 * \param - pHddCtx
5863 *
5864 * \return - None
5865 *
5866 * --------------------------------------------------------------------------*/
5867
5868static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
5869{
5870
5871 VOS_STATUS vos_status;
5872 /* Block any further calls */
5873 atomic_set(&pHddCtx->isRestartInProgress, 1);
5874 /* Cleanup */
5875 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
5876 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005877 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005878 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
5879 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005880 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005881
5882}
5883
5884/**---------------------------------------------------------------------------
5885 *
5886 * \brief wlan_hdd_framework_restart
5887 *
5888 * This function uses a cfg80211 API to start a framework initiated WLAN
5889 * driver module unload/load.
5890 *
5891 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
5892 *
5893 *
5894 * \param - pHddCtx
5895 *
5896 * \return - VOS_STATUS_SUCCESS: Success
5897 * VOS_STATUS_E_EMPTY: Adapter is Empty
5898 * VOS_STATUS_E_NOMEM: No memory
5899
5900 * --------------------------------------------------------------------------*/
5901
5902static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
5903{
5904 VOS_STATUS status = VOS_STATUS_SUCCESS;
5905 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5906 int len = (sizeof (struct ieee80211_mgmt));
5907 struct ieee80211_mgmt *mgmt = NULL;
5908
5909 /* Prepare the DEAUTH managment frame with reason code */
5910 mgmt = kzalloc(len, GFP_KERNEL);
5911 if(mgmt == NULL)
5912 {
5913 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1250df42012-12-10 14:31:52 -08005914 "%s: memory allocation failed (%d bytes)", __func__, len);
Jeff Johnsone7245742012-09-05 17:12:55 -07005915 return VOS_STATUS_E_NOMEM;
5916 }
5917 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
5918
5919 /* Iterate over all adapters/devices */
5920 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5921 do
5922 {
5923 if( (status == VOS_STATUS_SUCCESS) &&
5924 pAdapterNode &&
5925 pAdapterNode->pAdapter)
5926 {
5927 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5928 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
5929 pAdapterNode->pAdapter->dev->name,
5930 pAdapterNode->pAdapter->device_mode,
5931 pHddCtx->hdd_restart_retries + 1);
5932 /*
5933 * CFG80211 event to restart the driver
5934 *
5935 * 'cfg80211_send_unprot_deauth' sends a
5936 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
5937 * of SME(Linux Kernel) state machine.
5938 *
5939 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
5940 * the driver.
5941 *
5942 */
5943
5944 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
5945 }
5946 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5947 pAdapterNode = pNext;
5948 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
5949
5950
5951 /* Free the allocated management frame */
5952 kfree(mgmt);
5953
5954 /* Retry until we unload or reach max count */
5955 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
5956 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
5957
5958 return status;
5959
5960}
5961/**---------------------------------------------------------------------------
5962 *
5963 * \brief wlan_hdd_restart_timer_cb
5964 *
5965 * Restart timer callback. An internal function.
5966 *
5967 * \param - User data:
5968 *
5969 * \return - None
5970 *
5971 * --------------------------------------------------------------------------*/
5972
5973void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
5974{
5975 hdd_context_t *pHddCtx = usrDataForCallback;
5976 wlan_hdd_framework_restart(pHddCtx);
5977 return;
5978
5979}
5980
5981
5982/**---------------------------------------------------------------------------
5983 *
5984 * \brief wlan_hdd_restart_driver
5985 *
5986 * This function sends an event to supplicant to restart the WLAN driver.
5987 *
5988 * This function is called from vos_wlanRestart.
5989 *
5990 * \param - pHddCtx
5991 *
5992 * \return - VOS_STATUS_SUCCESS: Success
5993 * VOS_STATUS_E_EMPTY: Adapter is Empty
5994 * VOS_STATUS_E_ALREADY: Request already in progress
5995
5996 * --------------------------------------------------------------------------*/
5997VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
5998{
5999 VOS_STATUS status = VOS_STATUS_SUCCESS;
6000
6001 /* A tight check to make sure reentrancy */
6002 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6003 {
6004 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6005 "%s: WLAN restart is already in progress", __func__);
6006
6007 return VOS_STATUS_E_ALREADY;
6008 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006009 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006010#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006011 wcnss_reset_intr();
6012#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006013
Jeff Johnsone7245742012-09-05 17:12:55 -07006014 return status;
6015}
6016
6017
Jeff Johnson295189b2012-06-20 16:38:30 -07006018//Register the module init/exit functions
6019module_init(hdd_module_init);
6020module_exit(hdd_module_exit);
6021
6022MODULE_LICENSE("Dual BSD/GPL");
6023MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6024MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6025
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006026module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6027 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006028
6029module_param_call(fwpath, fwpath_changed_handler, param_get_string, fwpath,
6030 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);