blob: d001fa65d056554cfbc30c252460f463f19ba40d [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/*========================================================================
43
44 \file wlan_hdd_main.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
54/**=========================================================================
55
56 EDIT HISTORY FOR FILE
57
58
59 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
61
62
63 $Header:$ $DateTime: $ $Author: $
64
65
66 when who what, where, why
67 -------- --- --------------------------------------------------------
68 04/5/09 Shailender Created module.
69 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
70 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
71 ==========================================================================*/
72
73/*--------------------------------------------------------------------------
74 Include Files
75 ------------------------------------------------------------------------*/
76//#include <wlan_qct_driver.h>
77#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070078#include <vos_api.h>
79#include <vos_sched.h>
80#include <vos_power.h>
81#include <linux/etherdevice.h>
82#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070083#ifdef ANI_BUS_TYPE_PLATFORM
84#include <linux/wcnss_wlan.h>
85#endif //ANI_BUS_TYPE_PLATFORM
86#ifdef ANI_BUS_TYPE_PCI
87#include "wcnss_wlan.h"
88#endif /* ANI_BUS_TYPE_PCI */
89#include <wlan_hdd_tx_rx.h>
90#include <palTimer.h>
91#include <wniApi.h>
92#include <wlan_nlink_srv.h>
93#include <wlan_btc_svc.h>
94#include <wlan_hdd_cfg.h>
95#include <wlan_ptt_sock_svc.h>
96#include <wlan_hdd_wowl.h>
97#include <wlan_hdd_misc.h>
98#include <wlan_hdd_wext.h>
99#ifdef WLAN_BTAMP_FEATURE
100#include <bap_hdd_main.h>
101#include <bapInternal.h>
102#endif // WLAN_BTAMP_FEATURE
103
Jeff Johnson295189b2012-06-20 16:38:30 -0700104#include <linux/wireless.h>
105#include <net/cfg80211.h>
106#include "wlan_hdd_cfg80211.h"
107#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700108#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700109int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include "sapApi.h"
111#include <linux/semaphore.h>
112#include <mach/subsystem_restart.h>
113#include <wlan_hdd_hostapd.h>
114#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700115#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700116#include "wlan_hdd_dev_pwr.h"
117#ifdef WLAN_BTAMP_FEATURE
118#include "bap_hdd_misc.h"
119#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700120#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700121#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800122#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530123#ifdef FEATURE_WLAN_TDLS
124#include "wlan_hdd_tdls.h"
125#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700126
127#ifdef MODULE
128#define WLAN_MODULE_NAME module_name(THIS_MODULE)
129#else
130#define WLAN_MODULE_NAME "wlan"
131#endif
132
133#ifdef TIMER_MANAGER
134#define TIMER_MANAGER_STR " +TIMER_MANAGER"
135#else
136#define TIMER_MANAGER_STR ""
137#endif
138
139#ifdef MEMORY_DEBUG
140#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
141#else
142#define MEMORY_DEBUG_STR ""
143#endif
144
145/* the Android framework expects this param even though we don't use it */
146#define BUF_LEN 20
147static char fwpath[BUF_LEN];
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700148#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700149static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700150#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700151
Jeff Johnsone7245742012-09-05 17:12:55 -0700152/*
153 * The rate at which the driver sends RESTART event to supplicant
154 * once the function 'vos_wlanRestart()' is called
155 *
156 */
157#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
158#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800159#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700160static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700161#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700162/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700163static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700164
165//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700166static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
167static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
168static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
169void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800170void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700171
Jeff Johnson295189b2012-06-20 16:38:30 -0700172v_U16_t hdd_select_queue(struct net_device *dev,
173 struct sk_buff *skb);
174
175#ifdef WLAN_FEATURE_PACKET_FILTERING
176static void hdd_set_multicast_list(struct net_device *dev);
177#endif
178
179void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
180
181extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800182#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
183void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
184static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
185static VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
186#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700187static int hdd_netdev_notifier_call(struct notifier_block * nb,
188 unsigned long state,
189 void *ndev)
190{
191 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700192 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700193 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700194#ifdef WLAN_BTAMP_FEATURE
195 VOS_STATUS status;
196 hdd_context_t *pHddCtx;
197#endif
198
199 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700200 if ((strncmp(dev->name, "wlan", 4)) &&
201 (strncmp(dev->name, "p2p", 3)))
Jeff Johnson295189b2012-06-20 16:38:30 -0700202 return NOTIFY_DONE;
203
Jeff Johnson295189b2012-06-20 16:38:30 -0700204 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700205 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700206
Jeff Johnson27cee452013-03-27 11:10:24 -0700207 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700208 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800209 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700210 VOS_ASSERT(0);
211 return NOTIFY_DONE;
212 }
213
Jeff Johnson27cee452013-03-27 11:10:24 -0700214 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
215 if (NULL == pHddCtx)
216 {
217 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
218 VOS_ASSERT(0);
219 return NOTIFY_DONE;
220 }
221
222 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
223 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700224
225 switch (state) {
226 case NETDEV_REGISTER:
227 break;
228
229 case NETDEV_UNREGISTER:
230 break;
231
232 case NETDEV_UP:
233 break;
234
235 case NETDEV_DOWN:
236 break;
237
238 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700239 if(TRUE == pAdapter->isLinkUpSvcNeeded)
240 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700241 break;
242
243 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700244 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700245 {
246 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800247 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700248 hdd_abort_mac_scan(pAdapter->pHddCtx);
249 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800250 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700251 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
252 if(!result)
253 {
254 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800255 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700256 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700257 }
258 }
259 else
260 {
261 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700262 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700263 }
264#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700265 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700266 status = WLANBAP_StopAmp();
267 if(VOS_STATUS_SUCCESS != status )
268 {
269 pHddCtx->isAmpAllowed = VOS_TRUE;
270 hddLog(VOS_TRACE_LEVEL_FATAL,
271 "%s: Failed to stop AMP", __func__);
272 }
273 else
274 {
275 //a state m/c implementation in PAL is TBD to avoid this delay
276 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700277 if ( pHddCtx->isAmpAllowed )
278 {
279 WLANBAP_DeregisterFromHCI();
280 pHddCtx->isAmpAllowed = VOS_FALSE;
281 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700282 }
283#endif //WLAN_BTAMP_FEATURE
284 break;
285
286 default:
287 break;
288 }
289
290 return NOTIFY_DONE;
291}
292
293struct notifier_block hdd_netdev_notifier = {
294 .notifier_call = hdd_netdev_notifier_call,
295};
296
297/*---------------------------------------------------------------------------
298 * Function definitions
299 *-------------------------------------------------------------------------*/
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800300int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700301void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
302void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700303//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700304static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700305#ifndef MODULE
306/* current con_mode - used only for statically linked driver
307 * con_mode is changed by userspace to indicate a mode change which will
308 * result in calling the module exit and init functions. The module
309 * exit function will clean up based on the value of con_mode prior to it
310 * being changed by userspace. So curr_con_mode records the current con_mode
311 * for exit when con_mode becomes the next mode for init
312 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700313static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700314#endif
315
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800316/**---------------------------------------------------------------------------
317
318 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
319
320 Called immediately after the cfg.ini is read in order to configure
321 the desired trace levels.
322
323 \param - moduleId - module whose trace level is being configured
324 \param - bitmask - bitmask of log levels to be enabled
325
326 \return - void
327
328 --------------------------------------------------------------------------*/
329static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
330{
331 wpt_tracelevel level;
332
333 /* if the bitmask is the default value, then a bitmask was not
334 specified in cfg.ini, so leave the logging level alone (it
335 will remain at the "compiled in" default value) */
336 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
337 {
338 return;
339 }
340
341 /* a mask was specified. start by disabling all logging */
342 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
343
344 /* now cycle through the bitmask until all "set" bits are serviced */
345 level = VOS_TRACE_LEVEL_FATAL;
346 while (0 != bitmask)
347 {
348 if (bitmask & 1)
349 {
350 vos_trace_setValue(moduleId, level, 1);
351 }
352 level++;
353 bitmask >>= 1;
354 }
355}
356
357
Jeff Johnson295189b2012-06-20 16:38:30 -0700358/**---------------------------------------------------------------------------
359
360 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
361
362 Called immediately after the cfg.ini is read in order to configure
363 the desired trace levels in the WDI.
364
365 \param - moduleId - module whose trace level is being configured
366 \param - bitmask - bitmask of log levels to be enabled
367
368 \return - void
369
370 --------------------------------------------------------------------------*/
371static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
372{
373 wpt_tracelevel level;
374
375 /* if the bitmask is the default value, then a bitmask was not
376 specified in cfg.ini, so leave the logging level alone (it
377 will remain at the "compiled in" default value) */
378 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
379 {
380 return;
381 }
382
383 /* a mask was specified. start by disabling all logging */
384 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
385
386 /* now cycle through the bitmask until all "set" bits are serviced */
387 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
388 while (0 != bitmask)
389 {
390 if (bitmask & 1)
391 {
392 wpalTraceSetLevel(moduleId, level, 1);
393 }
394 level++;
395 bitmask >>= 1;
396 }
397}
Jeff Johnson295189b2012-06-20 16:38:30 -0700398
399int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
400{
401 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
402 hdd_priv_data_t priv_data;
403 tANI_U8 *command = NULL;
404 int ret = 0;
405
406 if (NULL == pAdapter)
407 {
408 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700409 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700410 ret = -ENODEV;
411 goto exit;
412 }
413
Jeff Johnsone7245742012-09-05 17:12:55 -0700414 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700415 {
416 ret = -EINVAL;
417 goto exit;
418 }
419
420 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
421 {
422 ret = -EFAULT;
423 goto exit;
424 }
425
426 command = kmalloc(priv_data.total_len, GFP_KERNEL);
427 if (!command)
428 {
429 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700430 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700431 ret = -ENOMEM;
432 goto exit;
433 }
434
435 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
436 {
437 ret = -EFAULT;
438 goto exit;
439 }
440
441 if ((SIOCDEVPRIVATE + 1) == cmd)
442 {
443 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
444
445 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700446 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700447
448 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
449 {
450 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
451 sizeof(tSirMacAddr)))
452 {
453 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700454 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700455 ret = -EFAULT;
456 }
457 }
Amar Singhal0974e402013-02-12 14:27:46 -0800458 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700459 {
Amar Singhal0974e402013-02-12 14:27:46 -0800460 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700461 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800462
Jeff Johnson295189b2012-06-20 16:38:30 -0700463 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800464
465 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700466 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700467 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800468 "%s: SetBandCommand Info comm %s UL %d, TL %d", __func__, command, priv_data.used_len, priv_data.total_len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700469 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800470 ret = hdd_setBand_helper(dev, ptr);
471 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700472 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
473 {
474 char *country_code;
475
476 country_code = command + 8;
477 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
478 pAdapter, pHddCtx->pvosContext);
479 if( 0 != ret )
480 {
481 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
482 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
483
484 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700485 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800486#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
487 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
488 {
489 tANI_U8 *value = command;
490 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
491 tANI_U8 revision = 0;
492 eHalStatus status = eHAL_STATUS_SUCCESS;
493 v_REGDOMAIN_t regId;
494
495 status = hdd_parse_countryrev(value, countryCode, &revision);
496 if (eHAL_STATUS_SUCCESS != status)
497 {
498 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
499 "%s: Failed to parse country revision information", __func__);
500 ret = -EINVAL;
501 goto exit;
502 }
503
504 /* Validate country code */
505 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
506 if (eHAL_STATUS_SUCCESS != status)
507 {
508 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
509 "%s: Invalid country code %s", __func__, countryCode);
510 ret = -EINVAL;
511 goto exit;
512 }
513
514 /* Validate revision */
515 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
516 {
517 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
518 "%s: Invalid revision %d", __func__, revision);
519 ret = -EINVAL;
520 goto exit;
521 }
522
523 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
524 pAdapter, pHddCtx->pvosContext);
525 if (0 != ret)
526 {
527 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
528 "%s: SME Change Country code fail ret=%d", __func__, ret);
529 ret = -EINVAL;
530 goto exit;
531 }
532
533 if (0 == strncmp(countryCode, "KR", 2))
534 {
535 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
536 revision);
537 if (eHAL_STATUS_SUCCESS != status)
538 {
539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
540 "%s: Failed to build valid channel list", __func__);
541 ret = -EINVAL;
542 goto exit;
543 }
544 }
545 }
546#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700547 /*
548 command should be a string having format
549 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
550 */
Amar Singhal0974e402013-02-12 14:27:46 -0800551 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700552 {
Amar Singhal0974e402013-02-12 14:27:46 -0800553 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700554
555 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700556 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700557
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800558 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700559 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800560 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
561 {
562 int suspend = 0;
563 tANI_U8 *ptr = (tANI_U8*)command + 15;
564
565 suspend = *ptr - '0';
566 hdd_set_wlan_suspend_mode(suspend);
567 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800568#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
569 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
570 {
571 tANI_U8 *value = command;
572 int rssi = 0;
573 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
574 eHalStatus status = eHAL_STATUS_SUCCESS;
575
576 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
577 value = value + 15;
578
579 sscanf(value, "%d", &rssi);
580 lookUpThreshold = abs(rssi);
581 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
582 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
583 {
584 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
585 "Neighbor lookup threshold value %d is out of range"
586 " (Min: %d Max: %d)", lookUpThreshold,
587 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
588 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
589 ret = -EINVAL;
590 goto exit;
591 }
592
593 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
594 "%s: Received Command to Set Roam trigger"
595 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
596
597 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
598 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
599 if (eHAL_STATUS_SUCCESS != status)
600 {
601 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
602 "%s: Failed to set roam trigger, try again", __func__);
603 ret = -EPERM;
604 goto exit;
605 }
606
607 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
608 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
609 }
610 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
611 {
612 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
613 int rssi = (-1) * lookUpThreshold;
614 char extra[32];
615 tANI_U8 len = 0;
616
617 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
618 if (copy_to_user(priv_data.buf, &extra, len + 1))
619 {
620 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
621 "%s: failed to copy data to user buffer", __func__);
622 ret = -EFAULT;
623 goto exit;
624 }
625 }
626 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
627 {
628 tANI_U8 *value = command;
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700629 tANI_U16 emptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800630 /* input refresh period is in terms of seconds */
631 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
632 value = value + 18;
633 /* Convert the value from ascii to integer */
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700634 ret = kstrtou16(value, 10, &emptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800635 if (ret < 0)
636 {
637 /* If the input value is greater than max value of datatype, then also
638 kstrtou16 fails */
639 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
640 "%s: kstrtou16 failed ",
641 "Input value may be out of range[%d - %d]",
642 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700643 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
644 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800645 ret = -EINVAL;
646 goto exit;
647 }
648
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700649 emptyScanRefreshPeriod = emptyScanRefreshPeriod * 1000;
650 if ((emptyScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
651 (emptyScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800652 {
653 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700654 "Empty scan refresh period value %d is out of range"
655 " (Min: %d Max: %d)", emptyScanRefreshPeriod/1000,
656 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
657 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800658 ret = -EINVAL;
659 goto exit;
660 }
661
662 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
663 "%s: Received Command to Set roam scan period"
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700664 " (Empty Scan refresh period) = %d", __func__, emptyScanRefreshPeriod/1000);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800665
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700666 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = emptyScanRefreshPeriod;
667 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), emptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800668 }
669 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
670 {
671 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
672 char extra[32];
673 tANI_U8 len = 0;
674
675 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
676 /* Returned value is in units of seconds */
677 if (copy_to_user(priv_data.buf, &extra, len + 1))
678 {
679 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
680 "%s: failed to copy data to user buffer", __func__);
681 ret = -EFAULT;
682 goto exit;
683 }
684 }
685#endif
686#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
687 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
688 {
689 tANI_U8 *value = command;
690 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
691
692 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
693 value = value + 13;
694 /* Convert the value from ascii to integer */
695 ret = kstrtou8(value, 10, &roamRssiDiff);
696 if (ret < 0)
697 {
698 /* If the input value is greater than max value of datatype, then also
699 kstrtou8 fails */
700 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
701 "%s: kstrtou8 failed range [%d - %d]", __func__,
702 CFG_ROAM_RSSI_DIFF_MIN,
703 CFG_ROAM_RSSI_DIFF_MAX);
704 ret = -EINVAL;
705 goto exit;
706 }
707
708 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
709 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
710 {
711 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
712 "Roam rssi diff value %d is out of range"
713 " (Min: %d Max: %d)", roamRssiDiff,
714 CFG_ROAM_RSSI_DIFF_MIN,
715 CFG_ROAM_RSSI_DIFF_MAX);
716 ret = -EINVAL;
717 goto exit;
718 }
719
720 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
721 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
722
723 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
724 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
725 }
726 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
727 {
728 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
729 char extra[32];
730 tANI_U8 len = 0;
731
732 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
733 if (copy_to_user(priv_data.buf, &extra, len + 1))
734 {
735 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
736 "%s: failed to copy data to user buffer", __func__);
737 ret = -EFAULT;
738 goto exit;
739 }
740 }
741#endif
742#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
743 else if (strncmp(command, "GETBAND", 7) == 0)
744 {
745 int band = -1;
746 char extra[32];
747 tANI_U8 len = 0;
748 hdd_getBand_helper(pHddCtx, &band);
749
750 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
751 if (copy_to_user(priv_data.buf, &extra, len + 1))
752 {
753 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
754 "%s: failed to copy data to user buffer", __func__);
755 ret = -EFAULT;
756 goto exit;
757 }
758 }
759 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
760 {
761 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
762 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
763 tANI_U8 revision = 0;
764 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
765 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
766 char extra[32] = {0};
767 tANI_U8 len = 0;
768
769 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
770 {
771 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
772 "%s: failed to get country code", __func__);
773 ret = -EFAULT;
774 goto exit;
775 }
776 pBuf[uBufLen] = '\0';
777 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
778
779 if (0 == strncmp(pBuf, "KR", 2))
780 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
781 else
782 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
783
784 if (copy_to_user(priv_data.buf, &extra, len + 1))
785 {
786 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
787 "%s: failed to copy data to user buffer", __func__);
788 ret = -EFAULT;
789 goto exit;
790 }
791 }
792 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
793 {
794 tANI_U8 *value = command;
795 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
796 tANI_U8 numChannels = 0;
797 eHalStatus status = eHAL_STATUS_SUCCESS;
798
799 status = hdd_parse_channellist(value, ChannelList, &numChannels);
800 if (eHAL_STATUS_SUCCESS != status)
801 {
802 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
803 "%s: Failed to parse channel list information", __func__);
804 ret = -EINVAL;
805 goto exit;
806 }
807
808 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
809 {
810 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
811 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
812 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
813 ret = -EINVAL;
814 goto exit;
815 }
816 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
817 numChannels);
818 if (eHAL_STATUS_SUCCESS != status)
819 {
820 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
821 "%s: Failed to update channel list information", __func__);
822 ret = -EINVAL;
823 goto exit;
824 }
825 }
826 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
827 {
828 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
829 tANI_U8 numChannels = 0;
830 tANI_U8 len = 0, j = 0;
831 char extra[128] = {0};
832
833 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
834 ChannelList, &numChannels ))
835 {
836 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
837 "%s: failed to get roam scan channel list", __func__);
838 ret = -EFAULT;
839 goto exit;
840 }
841 /* output channel list is of the format
842 [Number of roam scan channels][Channel1][Channel2]... */
843 /* copy the number of channels in the 0th index */
844 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
845 for (j = 0; (j < numChannels); j++)
846 {
847 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
848 }
849
850 if (copy_to_user(priv_data.buf, &extra, len + 1))
851 {
852 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
853 "%s: failed to copy data to user buffer", __func__);
854 ret = -EFAULT;
855 goto exit;
856 }
857 }
858#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700859 else {
860 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
861 __func__, command);
862 }
863
Jeff Johnson295189b2012-06-20 16:38:30 -0700864 }
865exit:
866 if (command)
867 {
868 kfree(command);
869 }
870 return ret;
871}
872
Srinivas Girigowdade697412013-02-14 16:31:48 -0800873#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
874void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
875{
876 eCsrBand band = -1;
877 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
878 switch (band)
879 {
880 case eCSR_BAND_ALL:
881 *pBand = WLAN_HDD_UI_BAND_AUTO;
882 break;
883
884 case eCSR_BAND_24:
885 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
886 break;
887
888 case eCSR_BAND_5G:
889 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
890 break;
891
892 default:
893 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
894 *pBand = -1;
895 break;
896 }
897}
898
899/**---------------------------------------------------------------------------
900
901 \brief hdd_parse_countryrev() - HDD Parse country code revision
902
903 This function parses the country code revision passed in the format
904 SETCOUNTRYREV<space><Country code><space>revision
905
906 \param - pValue Pointer to input country code revision
907 \param - pCountryCode Pointer to local output array to record country code
908 \param - pRevision Pointer to store revision integer number
909
910 \return - 0 for success non-zero for failure
911
912 --------------------------------------------------------------------------*/
913VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
914{
915 tANI_U8 *inPtr = pValue;
916 int tempInt;
917
918 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
919 /*no argument after the command*/
920 if (NULL == inPtr)
921 {
922 return -EINVAL;
923 }
924
925 /*no space after the command*/
926 else if (SPACE_ASCII_VALUE != *inPtr)
927 {
928 return -EINVAL;
929 }
930
931 /*removing empty spaces*/
932 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
933
934 /*no argument followed by spaces*/
935 if ('\0' == *inPtr)
936 {
937 return -EINVAL;
938 }
939
940 /*getting the first argument ie the country code */
941 sscanf(inPtr, "%s ", pCountryCode);
942
943 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
944 "Country code is : %s", pCountryCode);
945
946 /*inPtr pointing to the beginning of first space after country code */
947 inPtr = strpbrk( inPtr, " " );
948 /*no revision number after the country code argument */
949 if (NULL == inPtr)
950 {
951 return -EINVAL;
952 }
953
954 inPtr++;
955
956 /*removing empty space*/
957 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
958
959 /*no channel list after the number of channels argument and spaces*/
960 if (0 == strncmp(pCountryCode, "KR", 2))
961 {
962 if ('\0' == *inPtr)
963 {
964 return -EINVAL;
965 }
966
967 sscanf(inPtr, "%d", &tempInt);
968 *pRevision = tempInt;
969 }
970 else
971 {
972 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
973 "Revision input is required only for Country KR");
974 return -EINVAL;
975 }
976 return VOS_STATUS_SUCCESS;
977}
978
979/**---------------------------------------------------------------------------
980
981 \brief hdd_parse_channellist() - HDD Parse channel list
982
983 This function parses the channel list passed in the format
984 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -0700985 if the Number of channels (N) does not match with the actual number of channels passed
986 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
987 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
988 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
989 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -0800990
991 \param - pValue Pointer to input channel list
992 \param - ChannelList Pointer to local output array to record channel list
993 \param - pNumChannels Pointer to number of roam scan channels
994
995 \return - 0 for success non-zero for failure
996
997 --------------------------------------------------------------------------*/
998VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
999{
1000 tANI_U8 *inPtr = pValue;
1001 int tempInt;
1002 int j = 0;
1003 int v = 0;
1004 char buf[32];
1005
1006 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1007 /*no argument after the command*/
1008 if (NULL == inPtr)
1009 {
1010 return -EINVAL;
1011 }
1012
1013 /*no space after the command*/
1014 else if (SPACE_ASCII_VALUE != *inPtr)
1015 {
1016 return -EINVAL;
1017 }
1018
1019 /*removing empty spaces*/
1020 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
1021
1022 /*no argument followed by spaces*/
1023 if ('\0' == *inPtr)
1024 {
1025 return -EINVAL;
1026 }
1027
1028 /*getting the first argument ie the number of channels*/
1029 sscanf(inPtr, "%s ", buf);
1030 v = kstrtos32(buf, 10, &tempInt);
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001031 if ((v < 0) || (tempInt <= 0)) return -EINVAL;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001032
1033 *pNumChannels = tempInt;
1034
1035 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1036 "Number of channels are: %d", *pNumChannels);
1037
1038 for (j = 0; j < (*pNumChannels); j++)
1039 {
1040 /*inPtr pointing to the beginning of first space after number of channels*/
1041 inPtr = strpbrk( inPtr, " " );
1042 /*no channel list after the number of channels argument*/
1043 if (NULL == inPtr)
1044 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001045 if (0 != j)
1046 {
1047 *pNumChannels = j;
1048 return VOS_STATUS_SUCCESS;
1049 }
1050 else
1051 {
1052 return -EINVAL;
1053 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001054 }
1055
1056 /*removing empty space*/
1057 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1058
1059 /*no channel list after the number of channels argument and spaces*/
1060 if ( '\0' == *inPtr )
1061 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001062 if (0 != j)
1063 {
1064 *pNumChannels = j;
1065 return VOS_STATUS_SUCCESS;
1066 }
1067 else
1068 {
1069 return -EINVAL;
1070 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001071 }
1072
1073 sscanf(inPtr, "%s ", buf);
1074 v = kstrtos32(buf, 10, &tempInt);
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001075 if ((v < 0) || (tempInt <= 0)) return -EINVAL;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001076 pChannelList[j] = tempInt;
1077
1078 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1079 "Channel %d added to preferred channel list",
1080 pChannelList[j] );
1081 }
1082
Srinivas Girigowdade697412013-02-14 16:31:48 -08001083 return VOS_STATUS_SUCCESS;
1084}
1085
1086#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001087/**---------------------------------------------------------------------------
1088
1089 \brief hdd_open() - HDD Open function
1090
1091 This is called in response to ifconfig up
1092
1093 \param - dev Pointer to net_device structure
1094
1095 \return - 0 for success non-zero for failure
1096
1097 --------------------------------------------------------------------------*/
1098int hdd_open (struct net_device *dev)
1099{
1100 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1101 hdd_context_t *pHddCtx;
1102 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1103 VOS_STATUS status;
1104 v_BOOL_t in_standby = TRUE;
1105
1106 if (NULL == pAdapter)
1107 {
1108 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001109 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001110 return -ENODEV;
1111 }
1112
1113 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1114 if (NULL == pHddCtx)
1115 {
1116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001117 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001118 return -ENODEV;
1119 }
1120
1121 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1122 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1123 {
1124 if( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
1125 {
1126 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of "
1127 "standby", __func__, pAdapter->device_mode);
1128 in_standby = FALSE;
1129 break;
1130 }
1131 else
1132 {
1133 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1134 pAdapterNode = pNext;
1135 }
1136 }
1137
1138 if (TRUE == in_standby)
1139 {
1140 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
1141 {
1142 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
1143 "wlan out of power save", __func__);
1144 return -EINVAL;
1145 }
1146 }
1147
1148 pAdapter->event_flags |= DEVICE_IFACE_OPENED;
1149 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
1150 {
1151 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001152 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001153 /* Enable TX queues only when we are connected */
1154 netif_tx_start_all_queues(dev);
1155 }
1156
1157 return 0;
1158}
1159
1160int hdd_mon_open (struct net_device *dev)
1161{
1162 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1163
1164 if(pAdapter == NULL) {
1165 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001166 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001167 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001168 }
1169
1170 netif_start_queue(dev);
1171
1172 return 0;
1173}
1174/**---------------------------------------------------------------------------
1175
1176 \brief hdd_stop() - HDD stop function
1177
1178 This is called in response to ifconfig down
1179
1180 \param - dev Pointer to net_device structure
1181
1182 \return - 0 for success non-zero for failure
1183
1184 --------------------------------------------------------------------------*/
1185
1186int hdd_stop (struct net_device *dev)
1187{
1188 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1189 hdd_context_t *pHddCtx;
1190 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1191 VOS_STATUS status;
1192 v_BOOL_t enter_standby = TRUE;
1193
1194 ENTER();
1195
1196 if (NULL == pAdapter)
1197 {
1198 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001199 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001200 return -ENODEV;
1201 }
1202
1203 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1204 if (NULL == pHddCtx)
1205 {
1206 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001207 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001208 return -ENODEV;
1209 }
1210
1211 pAdapter->event_flags &= ~(DEVICE_IFACE_OPENED);
1212 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
1213 netif_tx_disable(pAdapter->dev);
1214 netif_carrier_off(pAdapter->dev);
1215
1216
1217 /* SoftAP ifaces should never go in power save mode
1218 making sure same here. */
1219 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
1220 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001221 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001222 )
1223 {
1224 /* SoftAP mode, so return from here */
1225 EXIT();
1226 return 0;
1227 }
1228
1229 /* Find if any iface is up then
1230 if any iface is up then can't put device to sleep/ power save mode. */
1231 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1232 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1233 {
1234 if ( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
1235 {
1236 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
1237 "put device to sleep", __func__, pAdapter->device_mode);
1238 enter_standby = FALSE;
1239 break;
1240 }
1241 else
1242 {
1243 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1244 pAdapterNode = pNext;
1245 }
1246 }
1247
1248 if (TRUE == enter_standby)
1249 {
1250 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
1251 "entering standby", __func__);
1252 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
1253 {
1254 /*log and return success*/
1255 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
1256 "wlan in power save", __func__);
1257 }
1258 }
1259
1260 EXIT();
1261 return 0;
1262}
1263
1264/**---------------------------------------------------------------------------
1265
1266 \brief hdd_uninit() - HDD uninit function
1267
1268 This is called during the netdev unregister to uninitialize all data
1269associated with the device
1270
1271 \param - dev Pointer to net_device structure
1272
1273 \return - void
1274
1275 --------------------------------------------------------------------------*/
1276static void hdd_uninit (struct net_device *dev)
1277{
1278 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1279
1280 ENTER();
1281
1282 do
1283 {
1284 if (NULL == pAdapter)
1285 {
1286 hddLog(VOS_TRACE_LEVEL_FATAL,
1287 "%s: NULL pAdapter", __func__);
1288 break;
1289 }
1290
1291 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1292 {
1293 hddLog(VOS_TRACE_LEVEL_FATAL,
1294 "%s: Invalid magic", __func__);
1295 break;
1296 }
1297
1298 if (NULL == pAdapter->pHddCtx)
1299 {
1300 hddLog(VOS_TRACE_LEVEL_FATAL,
1301 "%s: NULL pHddCtx", __func__);
1302 break;
1303 }
1304
1305 if (dev != pAdapter->dev)
1306 {
1307 hddLog(VOS_TRACE_LEVEL_FATAL,
1308 "%s: Invalid device reference", __func__);
1309 /* we haven't validated all cases so let this go for now */
1310 }
1311
1312 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
1313
1314 /* after uninit our adapter structure will no longer be valid */
1315 pAdapter->dev = NULL;
1316 pAdapter->magic = 0;
1317 } while (0);
1318
1319 EXIT();
1320}
1321
1322/**---------------------------------------------------------------------------
1323
1324 \brief hdd_release_firmware() -
1325
1326 This function calls the release firmware API to free the firmware buffer.
1327
1328 \param - pFileName Pointer to the File Name.
1329 pCtx - Pointer to the adapter .
1330
1331
1332 \return - 0 for success, non zero for failure
1333
1334 --------------------------------------------------------------------------*/
1335
1336VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
1337{
1338 VOS_STATUS status = VOS_STATUS_SUCCESS;
1339 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1340 ENTER();
1341
1342
1343 if (!strcmp(WLAN_FW_FILE, pFileName)) {
1344
1345 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
1346
1347 if(pHddCtx->fw) {
1348 release_firmware(pHddCtx->fw);
1349 pHddCtx->fw = NULL;
1350 }
1351 else
1352 status = VOS_STATUS_E_FAILURE;
1353 }
1354 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
1355 if(pHddCtx->nv) {
1356 release_firmware(pHddCtx->nv);
1357 pHddCtx->nv = NULL;
1358 }
1359 else
1360 status = VOS_STATUS_E_FAILURE;
1361
1362 }
1363
1364 EXIT();
1365 return status;
1366}
1367
1368/**---------------------------------------------------------------------------
1369
1370 \brief hdd_request_firmware() -
1371
1372 This function reads the firmware file using the request firmware
1373 API and returns the the firmware data and the firmware file size.
1374
1375 \param - pfileName - Pointer to the file name.
1376 - pCtx - Pointer to the adapter .
1377 - ppfw_data - Pointer to the pointer of the firmware data.
1378 - pSize - Pointer to the file size.
1379
1380 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
1381
1382 --------------------------------------------------------------------------*/
1383
1384
1385VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
1386{
1387 int status;
1388 VOS_STATUS retval = VOS_STATUS_SUCCESS;
1389 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1390 ENTER();
1391
1392 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
1393
1394 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
1395
1396 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1397 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
1398 __func__, pfileName);
1399 retval = VOS_STATUS_E_FAILURE;
1400 }
1401
1402 else {
1403 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
1404 *pSize = pHddCtx->fw->size;
1405 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
1406 __func__, *pSize);
1407 }
1408 }
1409 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
1410
1411 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
1412
1413 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
1414 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
1415 __func__, pfileName);
1416 retval = VOS_STATUS_E_FAILURE;
1417 }
1418
1419 else {
1420 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
1421 *pSize = pHddCtx->nv->size;
1422 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
1423 __func__, *pSize);
1424 }
1425 }
1426
1427 EXIT();
1428 return retval;
1429}
1430/**---------------------------------------------------------------------------
1431 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
1432
1433 This is the function invoked by SME to inform the result of a full power
1434 request issued by HDD
1435
1436 \param - callbackcontext - Pointer to cookie
1437 status - result of request
1438
1439 \return - None
1440
1441--------------------------------------------------------------------------*/
1442void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
1443{
1444 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
1445
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001446 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001447 if(&pHddCtx->full_pwr_comp_var)
1448 {
1449 complete(&pHddCtx->full_pwr_comp_var);
1450 }
1451}
1452
1453/**---------------------------------------------------------------------------
1454
1455 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
1456
1457 This is the function invoked by SME to inform the result of BMPS
1458 request issued by HDD
1459
1460 \param - callbackcontext - Pointer to cookie
1461 status - result of request
1462
1463 \return - None
1464
1465--------------------------------------------------------------------------*/
1466void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
1467{
1468
1469 struct completion *completion_var = (struct completion*) callbackContext;
1470
1471 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
1472 if(completion_var != NULL)
1473 {
1474 complete(completion_var);
1475 }
1476}
1477
1478/**---------------------------------------------------------------------------
1479
1480 \brief hdd_get_cfg_file_size() -
1481
1482 This function reads the configuration file using the request firmware
1483 API and returns the configuration file size.
1484
1485 \param - pCtx - Pointer to the adapter .
1486 - pFileName - Pointer to the file name.
1487 - pBufSize - Pointer to the buffer size.
1488
1489 \return - 0 for success, non zero for failure
1490
1491 --------------------------------------------------------------------------*/
1492
1493VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
1494{
1495 int status;
1496 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1497
1498 ENTER();
1499
1500 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
1501
1502 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1503 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
1504 status = VOS_STATUS_E_FAILURE;
1505 }
1506 else {
1507 *pBufSize = pHddCtx->fw->size;
1508 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
1509 release_firmware(pHddCtx->fw);
1510 pHddCtx->fw = NULL;
1511 }
1512
1513 EXIT();
1514 return VOS_STATUS_SUCCESS;
1515}
1516
1517/**---------------------------------------------------------------------------
1518
1519 \brief hdd_read_cfg_file() -
1520
1521 This function reads the configuration file using the request firmware
1522 API and returns the cfg data and the buffer size of the configuration file.
1523
1524 \param - pCtx - Pointer to the adapter .
1525 - pFileName - Pointer to the file name.
1526 - pBuffer - Pointer to the data buffer.
1527 - pBufSize - Pointer to the buffer size.
1528
1529 \return - 0 for success, non zero for failure
1530
1531 --------------------------------------------------------------------------*/
1532
1533VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
1534 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
1535{
1536 int status;
1537 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1538
1539 ENTER();
1540
1541 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
1542
1543 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1544 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
1545 return VOS_STATUS_E_FAILURE;
1546 }
1547 else {
1548 if(*pBufSize != pHddCtx->fw->size) {
1549 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
1550 "file size", __func__);
1551 release_firmware(pHddCtx->fw);
1552 pHddCtx->fw = NULL;
1553 return VOS_STATUS_E_FAILURE;
1554 }
1555 else {
1556 if(pBuffer) {
1557 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
1558 }
1559 release_firmware(pHddCtx->fw);
1560 pHddCtx->fw = NULL;
1561 }
1562 }
1563
1564 EXIT();
1565
1566 return VOS_STATUS_SUCCESS;
1567}
1568
1569/**---------------------------------------------------------------------------
1570
Jeff Johnson295189b2012-06-20 16:38:30 -07001571 \brief hdd_set_mac_address() -
1572
1573 This function sets the user specified mac address using
1574 the command ifconfig wlanX hw ether <mac adress>.
1575
1576 \param - dev - Pointer to the net device.
1577 - addr - Pointer to the sockaddr.
1578 \return - 0 for success, non zero for failure
1579
1580 --------------------------------------------------------------------------*/
1581
1582static int hdd_set_mac_address(struct net_device *dev, void *addr)
1583{
1584 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1585 struct sockaddr *psta_mac_addr = addr;
1586 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1587
1588 ENTER();
1589
1590 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
1591
1592#ifdef HDD_SESSIONIZE
1593 // set the MAC address though the STA ID CFG.
1594 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
1595 (v_U8_t *)&pAdapter->macAddressCurrent,
1596 sizeof( pAdapter->macAddressCurrent ),
1597 hdd_set_mac_addr_cb, VOS_FALSE );
1598#endif
1599
1600 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
1601
1602 EXIT();
1603 return halStatus;
1604}
1605
1606tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
1607{
1608 int i;
1609 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
1610 {
1611 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
1612 break;
1613 }
1614
1615 if( VOS_MAX_CONCURRENCY_PERSONA == i)
1616 return NULL;
1617
1618 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
1619 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
1620}
1621
1622void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
1623{
1624 int i;
1625 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
1626 {
1627 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
1628 {
1629 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
1630 break;
1631 }
1632 }
1633 return;
1634}
1635
1636#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1637 static struct net_device_ops wlan_drv_ops = {
1638 .ndo_open = hdd_open,
1639 .ndo_stop = hdd_stop,
1640 .ndo_uninit = hdd_uninit,
1641 .ndo_start_xmit = hdd_hard_start_xmit,
1642 .ndo_tx_timeout = hdd_tx_timeout,
1643 .ndo_get_stats = hdd_stats,
1644 .ndo_do_ioctl = hdd_ioctl,
1645 .ndo_set_mac_address = hdd_set_mac_address,
1646 .ndo_select_queue = hdd_select_queue,
1647#ifdef WLAN_FEATURE_PACKET_FILTERING
1648#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
1649 .ndo_set_rx_mode = hdd_set_multicast_list,
1650#else
1651 .ndo_set_multicast_list = hdd_set_multicast_list,
1652#endif //LINUX_VERSION_CODE
1653#endif
1654 };
Jeff Johnson295189b2012-06-20 16:38:30 -07001655 static struct net_device_ops wlan_mon_drv_ops = {
1656 .ndo_open = hdd_mon_open,
1657 .ndo_stop = hdd_stop,
1658 .ndo_uninit = hdd_uninit,
1659 .ndo_start_xmit = hdd_mon_hard_start_xmit,
1660 .ndo_tx_timeout = hdd_tx_timeout,
1661 .ndo_get_stats = hdd_stats,
1662 .ndo_do_ioctl = hdd_ioctl,
1663 .ndo_set_mac_address = hdd_set_mac_address,
1664 };
Jeff Johnson295189b2012-06-20 16:38:30 -07001665
1666#endif
1667
1668void hdd_set_station_ops( struct net_device *pWlanDev )
1669{
1670#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1671 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
1672 pWlanDev->netdev_ops = &wlan_drv_ops;
1673#else
1674 pWlanDev->open = hdd_open;
1675 pWlanDev->stop = hdd_stop;
1676 pWlanDev->uninit = hdd_uninit;
1677 pWlanDev->hard_start_xmit = NULL;
1678 pWlanDev->tx_timeout = hdd_tx_timeout;
1679 pWlanDev->get_stats = hdd_stats;
1680 pWlanDev->do_ioctl = hdd_ioctl;
1681 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
1682 pWlanDev->set_mac_address = hdd_set_mac_address;
1683#endif
1684}
1685
Jeff Johnsoneed415b2013-01-18 16:11:20 -08001686static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07001687{
1688 struct net_device *pWlanDev = NULL;
1689 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001690 /*
1691 * cfg80211 initialization and registration....
1692 */
1693 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
1694
Jeff Johnson295189b2012-06-20 16:38:30 -07001695 if(pWlanDev != NULL)
1696 {
1697
1698 //Save the pointer to the net_device in the HDD adapter
1699 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
1700
Jeff Johnson295189b2012-06-20 16:38:30 -07001701 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
1702
1703 pAdapter->dev = pWlanDev;
1704 pAdapter->pHddCtx = pHddCtx;
1705 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
1706
1707 init_completion(&pAdapter->session_open_comp_var);
1708 init_completion(&pAdapter->session_close_comp_var);
1709 init_completion(&pAdapter->disconnect_comp_var);
1710 init_completion(&pAdapter->linkup_event_var);
1711 init_completion(&pAdapter->cancel_rem_on_chan_var);
1712 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001713#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1714 init_completion(&pAdapter->offchannel_tx_event);
1715#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001716 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08001717#ifdef FEATURE_WLAN_TDLS
1718 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07001719 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001720 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08001721#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001722 init_completion(&pHddCtx->mc_sus_event_var);
1723 init_completion(&pHddCtx->tx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07001724 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07001725
Jeff Johnson295189b2012-06-20 16:38:30 -07001726 pAdapter->isLinkUpSvcNeeded = FALSE;
1727 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
1728 //Init the net_device structure
1729 strlcpy(pWlanDev->name, name, IFNAMSIZ);
1730
1731 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
1732 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
1733 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
1734 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
1735
1736 hdd_set_station_ops( pAdapter->dev );
1737
1738 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07001739 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
1740 pAdapter->wdev.wiphy = pHddCtx->wiphy;
1741 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07001742 /* set pWlanDev's parent to underlying device */
1743 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
1744 }
1745
1746 return pAdapter;
1747}
1748
1749VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
1750{
1751 struct net_device *pWlanDev = pAdapter->dev;
1752 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1753 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1754 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1755
1756 if( rtnl_lock_held )
1757 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001758 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07001759 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
1760 {
1761 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
1762 return VOS_STATUS_E_FAILURE;
1763 }
1764 }
1765 if (register_netdevice(pWlanDev))
1766 {
1767 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
1768 return VOS_STATUS_E_FAILURE;
1769 }
1770 }
1771 else
1772 {
1773 if(register_netdev(pWlanDev))
1774 {
1775 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
1776 return VOS_STATUS_E_FAILURE;
1777 }
1778 }
1779 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
1780
1781 return VOS_STATUS_SUCCESS;
1782}
1783
1784eHalStatus hdd_smeCloseSessionCallback(void *pContext)
1785{
1786 if(pContext != NULL)
1787 {
1788 clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags);
1789
1790 /* need to make sure all of our scheduled work has completed.
1791 * This callback is called from MC thread context, so it is safe to
1792 * to call below flush workqueue API from here.
1793 */
1794 flush_scheduled_work();
1795 complete(&((hdd_adapter_t*)pContext)->session_close_comp_var);
1796 }
1797 return eHAL_STATUS_SUCCESS;
1798}
1799
1800VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
1801{
1802 struct net_device *pWlanDev = pAdapter->dev;
1803 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1804 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1805 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1806 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1807 int rc = 0;
1808
1809 INIT_COMPLETION(pAdapter->session_open_comp_var);
1810 //Open a SME session for future operation
1811 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
1812 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
1813 if ( !HAL_STATUS_SUCCESS( halStatus ) )
1814 {
1815 hddLog(VOS_TRACE_LEVEL_FATAL,
1816 "sme_OpenSession() failed with status code %08d [x%08lx]",
1817 halStatus, halStatus );
1818 status = VOS_STATUS_E_FAILURE;
1819 goto error_sme_open;
1820 }
1821
1822 //Block on a completion variable. Can't wait forever though.
1823 rc = wait_for_completion_interruptible_timeout(
1824 &pAdapter->session_open_comp_var,
1825 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1826 if (!rc)
1827 {
1828 hddLog(VOS_TRACE_LEVEL_FATAL,
1829 "Session is not opened within timeout period code %08d", rc );
1830 status = VOS_STATUS_E_FAILURE;
1831 goto error_sme_open;
1832 }
1833
1834 // Register wireless extensions
1835 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
1836 {
1837 hddLog(VOS_TRACE_LEVEL_FATAL,
1838 "hdd_register_wext() failed with status code %08d [x%08lx]",
1839 halStatus, halStatus );
1840 status = VOS_STATUS_E_FAILURE;
1841 goto error_register_wext;
1842 }
1843 //Safe to register the hard_start_xmit function again
1844#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1845 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
1846#else
1847 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
1848#endif
1849
1850 //Set the Connection State to Not Connected
1851 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
1852
1853 //Set the default operation channel
1854 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
1855
1856 /* Make the default Auth Type as OPEN*/
1857 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
1858
1859 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
1860 {
1861 hddLog(VOS_TRACE_LEVEL_FATAL,
1862 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
1863 status, status );
1864 goto error_init_txrx;
1865 }
1866
1867 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1868
1869 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
1870 {
1871 hddLog(VOS_TRACE_LEVEL_FATAL,
1872 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
1873 status, status );
1874 goto error_wmm_init;
1875 }
1876
1877 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1878
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001879#ifdef FEATURE_WLAN_TDLS
1880 if(0 != wlan_hdd_tdls_init(pAdapter))
1881 {
1882 status = VOS_STATUS_E_FAILURE;
1883 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
1884 goto error_tdls_init;
1885 }
1886 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
1887#endif
1888
Jeff Johnson295189b2012-06-20 16:38:30 -07001889 return VOS_STATUS_SUCCESS;
1890
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001891#ifdef FEATURE_WLAN_TDLS
1892error_tdls_init:
1893 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1894 hdd_wmm_adapter_close(pAdapter);
1895#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001896error_wmm_init:
1897 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1898 hdd_deinit_tx_rx(pAdapter);
1899error_init_txrx:
1900 hdd_UnregisterWext(pWlanDev);
1901error_register_wext:
1902 if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
1903 {
1904 INIT_COMPLETION(pAdapter->session_close_comp_var);
1905 if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
1906 pAdapter->sessionId,
1907 hdd_smeCloseSessionCallback, pAdapter ) )
1908 {
1909 //Block on a completion variable. Can't wait forever though.
1910 wait_for_completion_interruptible_timeout(
1911 &pAdapter->session_close_comp_var,
1912 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1913 }
1914}
1915error_sme_open:
1916 return status;
1917}
1918
Jeff Johnson295189b2012-06-20 16:38:30 -07001919void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1920{
1921 hdd_cfg80211_state_t *cfgState;
1922
1923 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1924
1925 if( NULL != cfgState->buf )
1926 {
1927 int rc;
1928 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
1929 rc = wait_for_completion_interruptible_timeout(
1930 &pAdapter->tx_action_cnf_event,
1931 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
1932 if(!rc)
1933 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08001934 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001935 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
1936 }
1937 }
1938 return;
1939}
Jeff Johnson295189b2012-06-20 16:38:30 -07001940
1941void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1942{
1943 ENTER();
1944 switch ( pAdapter->device_mode )
1945 {
1946 case WLAN_HDD_INFRA_STATION:
1947 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07001948 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07001949 {
1950 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1951 {
1952 hdd_deinit_tx_rx( pAdapter );
1953 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1954 }
1955
1956 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
1957 {
1958 hdd_wmm_adapter_close( pAdapter );
1959 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1960 }
1961
Jeff Johnson295189b2012-06-20 16:38:30 -07001962 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001963#ifdef FEATURE_WLAN_TDLS
1964 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
1965 {
1966 wlan_hdd_tdls_exit(pAdapter);
1967 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
1968 }
1969#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001970
1971 break;
1972 }
1973
1974 case WLAN_HDD_SOFTAP:
1975 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07001976 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001977 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001978
1979 hdd_unregister_hostapd(pAdapter);
1980 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07001981 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07001982 break;
1983 }
1984
1985 case WLAN_HDD_MONITOR:
1986 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001987 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07001988 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1989 {
1990 hdd_deinit_tx_rx( pAdapter );
1991 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1992 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001993 if(NULL != pAdapterforTx)
1994 {
1995 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
1996 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001997 break;
1998 }
1999
2000
2001 default:
2002 break;
2003 }
2004
2005 EXIT();
2006}
2007
2008void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
2009{
2010 struct net_device *pWlanDev = pAdapter->dev;
2011
2012 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
2013 if( rtnl_held )
2014 {
2015 unregister_netdevice(pWlanDev);
2016 }
2017 else
2018 {
2019 unregister_netdev(pWlanDev);
2020 }
2021 // note that the pAdapter is no longer valid at this point
2022 // since the memory has been reclaimed
2023 }
2024
2025}
2026
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08002027void hdd_set_pwrparams(hdd_context_t *pHddCtx)
2028{
2029 tSirSetPowerParamsReq powerRequest = { 0 };
2030
2031 powerRequest.uIgnoreDTIM = 1;
2032
2033 if (pHddCtx->cfg_ini->enableModulatedDTIM)
2034 {
2035 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
2036 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2037 }
2038 else
2039 {
2040 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
2041 }
2042
2043 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
2044 *specified during Enter/Exit BMPS when LCD off*/
2045 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2046 NULL, eANI_BOOLEAN_FALSE);
2047 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2048 NULL, eANI_BOOLEAN_FALSE);
2049
2050 /* switch to the DTIM specified in cfg.ini */
2051 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2052 "Switch to DTIM%d", powerRequest.uListenInterval);
2053 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2054
2055}
2056
2057void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
2058{
2059 /*Switch back to DTIM 1*/
2060 tSirSetPowerParamsReq powerRequest = { 0 };
2061
2062 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
2063 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2064
2065 /* Update ignoreDTIM and ListedInterval in CFG with default values */
2066 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2067 NULL, eANI_BOOLEAN_FALSE);
2068 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2069 NULL, eANI_BOOLEAN_FALSE);
2070
2071 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2072 "Switch to DTIM%d",powerRequest.uListenInterval);
2073 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2074
2075}
2076
Jeff Johnson295189b2012-06-20 16:38:30 -07002077VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
2078{
2079 VOS_STATUS status = VOS_STATUS_SUCCESS;
2080
2081 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2082 {
2083 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2084 }
2085
2086 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2087 {
2088 sme_StartAutoBmpsTimer(pHddCtx->hHal);
2089 }
2090
2091 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2092 {
2093 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2094 }
2095
2096 return status;
2097}
2098
2099VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
2100{
2101 hdd_adapter_t *pAdapter = NULL;
2102 eHalStatus halStatus;
2103 VOS_STATUS status = VOS_STATUS_E_INVAL;
2104 v_BOOL_t disableBmps = FALSE;
2105 v_BOOL_t disableImps = FALSE;
2106
2107 switch(session_type)
2108 {
2109 case WLAN_HDD_INFRA_STATION:
2110 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002111 case WLAN_HDD_P2P_CLIENT:
2112 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002113 //Exit BMPS -> Is Sta/P2P Client is already connected
2114 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
2115 if((NULL != pAdapter)&&
2116 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2117 {
2118 disableBmps = TRUE;
2119 }
2120
2121 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
2122 if((NULL != pAdapter)&&
2123 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2124 {
2125 disableBmps = TRUE;
2126 }
2127
2128 //Exit both Bmps and Imps incase of Go/SAP Mode
2129 if((WLAN_HDD_SOFTAP == session_type) ||
2130 (WLAN_HDD_P2P_GO == session_type))
2131 {
2132 disableBmps = TRUE;
2133 disableImps = TRUE;
2134 }
2135
2136 if(TRUE == disableImps)
2137 {
2138 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2139 {
2140 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2141 }
2142 }
2143
2144 if(TRUE == disableBmps)
2145 {
2146 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2147 {
2148 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2149
2150 if(eHAL_STATUS_SUCCESS != halStatus)
2151 {
2152 status = VOS_STATUS_E_FAILURE;
2153 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
2154 VOS_ASSERT(0);
2155 return status;
2156 }
2157 }
2158
2159 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2160 {
2161 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
2162
2163 if(eHAL_STATUS_SUCCESS != halStatus)
2164 {
2165 status = VOS_STATUS_E_FAILURE;
2166 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
2167 VOS_ASSERT(0);
2168 return status;
2169 }
2170 }
2171 }
2172
2173 if((TRUE == disableBmps) ||
2174 (TRUE == disableImps))
2175 {
2176 /* Now, get the chip into Full Power now */
2177 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
2178 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
2179 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
2180
2181 if(halStatus != eHAL_STATUS_SUCCESS)
2182 {
2183 if(halStatus == eHAL_STATUS_PMC_PENDING)
2184 {
2185 //Block on a completion variable. Can't wait forever though
2186 wait_for_completion_interruptible_timeout(
2187 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
2188 }
2189 else
2190 {
2191 status = VOS_STATUS_E_FAILURE;
2192 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
2193 VOS_ASSERT(0);
2194 return status;
2195 }
2196 }
2197
2198 status = VOS_STATUS_SUCCESS;
2199 }
2200
2201 break;
2202 }
2203 return status;
2204}
2205
2206hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002207 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07002208 tANI_U8 rtnl_held )
2209{
2210 hdd_adapter_t *pAdapter = NULL;
2211 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
2212 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2213 VOS_STATUS exitbmpsStatus;
2214
2215 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
2216
2217 //Disable BMPS incase of Concurrency
2218 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
2219
2220 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
2221 {
2222 //Fail to Exit BMPS
2223 VOS_ASSERT(0);
2224 return NULL;
2225 }
2226
2227 switch(session_type)
2228 {
2229 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002230 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002231 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002232 {
2233 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2234
2235 if( NULL == pAdapter )
2236 return NULL;
2237
Jeff Johnsone7245742012-09-05 17:12:55 -07002238 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
2239 NL80211_IFTYPE_P2P_CLIENT:
2240 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07002241
Jeff Johnson295189b2012-06-20 16:38:30 -07002242 pAdapter->device_mode = session_type;
2243
2244 status = hdd_init_station_mode( pAdapter );
2245 if( VOS_STATUS_SUCCESS != status )
2246 goto err_free_netdev;
2247
2248 status = hdd_register_interface( pAdapter, rtnl_held );
2249 if( VOS_STATUS_SUCCESS != status )
2250 {
2251 hdd_deinit_adapter(pHddCtx, pAdapter);
2252 goto err_free_netdev;
2253 }
2254 //Stop the Interface TX queue.
2255 netif_tx_disable(pAdapter->dev);
2256 //netif_tx_disable(pWlanDev);
2257 netif_carrier_off(pAdapter->dev);
2258
2259 break;
2260 }
2261
Jeff Johnson295189b2012-06-20 16:38:30 -07002262 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002263 case WLAN_HDD_SOFTAP:
2264 {
2265 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
2266 if( NULL == pAdapter )
2267 return NULL;
2268
Jeff Johnson295189b2012-06-20 16:38:30 -07002269 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
2270 NL80211_IFTYPE_AP:
2271 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002272 pAdapter->device_mode = session_type;
2273
2274 status = hdd_init_ap_mode(pAdapter);
2275 if( VOS_STATUS_SUCCESS != status )
2276 goto err_free_netdev;
2277
2278 status = hdd_register_hostapd( pAdapter, rtnl_held );
2279 if( VOS_STATUS_SUCCESS != status )
2280 {
2281 hdd_deinit_adapter(pHddCtx, pAdapter);
2282 goto err_free_netdev;
2283 }
2284
2285 netif_tx_disable(pAdapter->dev);
2286 netif_carrier_off(pAdapter->dev);
2287
2288 hdd_set_conparam( 1 );
2289 break;
2290 }
2291 case WLAN_HDD_MONITOR:
2292 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002293 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2294 if( NULL == pAdapter )
2295 return NULL;
2296
2297 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
2298 pAdapter->device_mode = session_type;
2299 status = hdd_register_interface( pAdapter, rtnl_held );
2300#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
2301 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
2302#else
2303 pAdapter->dev->open = hdd_mon_open;
2304 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
2305#endif
2306 hdd_init_tx_rx( pAdapter );
2307 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2308 //Set adapter to be used for data tx. It will use either GO or softap.
2309 pAdapter->sessionCtx.monitor.pAdapterForTx =
2310 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07002311 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
2312 {
2313 pAdapter->sessionCtx.monitor.pAdapterForTx =
2314 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
2315 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002316 /* This workqueue will be used to transmit management packet over
2317 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07002318 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
2319 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
2320 return NULL;
2321 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07002322
Jeff Johnson295189b2012-06-20 16:38:30 -07002323 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
2324 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07002325 }
2326 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002327 case WLAN_HDD_FTM:
2328 {
2329 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2330
2331 if( NULL == pAdapter )
2332 return NULL;
2333 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
2334 * message while loading driver in FTM mode. */
2335 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
2336 pAdapter->device_mode = session_type;
2337 status = hdd_register_interface( pAdapter, rtnl_held );
2338 }
2339 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002340 default:
2341 {
2342 VOS_ASSERT(0);
2343 return NULL;
2344 }
2345 }
2346
2347
2348 if( VOS_STATUS_SUCCESS == status )
2349 {
2350 //Add it to the hdd's session list.
2351 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
2352 if( NULL == pHddAdapterNode )
2353 {
2354 status = VOS_STATUS_E_NOMEM;
2355 }
2356 else
2357 {
2358 pHddAdapterNode->pAdapter = pAdapter;
2359 status = hdd_add_adapter_back ( pHddCtx,
2360 pHddAdapterNode );
2361 }
2362 }
2363
2364 if( VOS_STATUS_SUCCESS != status )
2365 {
2366 if( NULL != pAdapter )
2367 {
2368 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
2369 pAdapter = NULL;
2370 }
2371 if( NULL != pHddAdapterNode )
2372 {
2373 vos_mem_free( pHddAdapterNode );
2374 }
2375
2376 goto resume_bmps;
2377 }
2378
2379 if(VOS_STATUS_SUCCESS == status)
2380 {
2381 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
2382
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07002383 //Initialize the WoWL service
2384 if(!hdd_init_wowl(pAdapter))
2385 {
2386 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
2387 goto err_free_netdev;
2388 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002389 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002390 return pAdapter;
2391
2392err_free_netdev:
2393 free_netdev(pAdapter->dev);
2394 wlan_hdd_release_intf_addr( pHddCtx,
2395 pAdapter->macAddressCurrent.bytes );
2396
2397resume_bmps:
2398 //If bmps disabled enable it
2399 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
2400 {
2401 hdd_enable_bmps_imps(pHddCtx);
2402 }
2403 return NULL;
2404}
2405
2406VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
2407 tANI_U8 rtnl_held )
2408{
2409 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
2410 VOS_STATUS status;
2411
2412 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
2413 if( VOS_STATUS_SUCCESS != status )
2414 return status;
2415
2416 while ( pCurrent->pAdapter != pAdapter )
2417 {
2418 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
2419 if( VOS_STATUS_SUCCESS != status )
2420 break;
2421
2422 pCurrent = pNext;
2423 }
2424 pAdapterNode = pCurrent;
2425 if( VOS_STATUS_SUCCESS == status )
2426 {
2427 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2428 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
2429 hdd_remove_adapter( pHddCtx, pAdapterNode );
2430 vos_mem_free( pAdapterNode );
2431
Jeff Johnson295189b2012-06-20 16:38:30 -07002432
2433 /* If there is a single session of STA/P2P client, re-enable BMPS */
2434 if ((!vos_concurrent_sessions_running()) &&
2435 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
2436 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
2437 {
2438 hdd_enable_bmps_imps(pHddCtx);
2439 }
2440
2441 return VOS_STATUS_SUCCESS;
2442 }
2443
2444 return VOS_STATUS_E_FAILURE;
2445}
2446
2447VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
2448{
2449 hdd_adapter_list_node_t *pHddAdapterNode;
2450 VOS_STATUS status;
2451
2452 ENTER();
2453
2454 do
2455 {
2456 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
2457 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
2458 {
2459 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
2460 vos_mem_free( pHddAdapterNode );
2461 }
2462 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
2463
2464 EXIT();
2465
2466 return VOS_STATUS_SUCCESS;
2467}
2468
2469void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
2470{
2471 v_U8_t addIE[1] = {0};
2472
2473 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2474 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
2475 eANI_BOOLEAN_FALSE) )
2476 {
2477 hddLog(LOGE,
2478 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
2479 }
2480
2481 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2482 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
2483 eANI_BOOLEAN_FALSE) )
2484 {
2485 hddLog(LOGE,
2486 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
2487 }
2488
2489 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2490 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
2491 eANI_BOOLEAN_FALSE) )
2492 {
2493 hddLog(LOGE,
2494 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
2495 }
2496}
2497
2498VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2499{
2500 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2501 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2502 union iwreq_data wrqu;
2503
2504 ENTER();
2505
2506 switch(pAdapter->device_mode)
2507 {
2508 case WLAN_HDD_INFRA_STATION:
2509 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002510 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002511 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
2512 {
2513 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
2514 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
2515 pAdapter->sessionId,
2516 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
2517 else
2518 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
2519 pAdapter->sessionId,
2520 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2521 //success implies disconnect command got queued up successfully
2522 if(halStatus == eHAL_STATUS_SUCCESS)
2523 {
2524 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
2525 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2526 }
2527 memset(&wrqu, '\0', sizeof(wrqu));
2528 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2529 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2530 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2531 }
2532 else
2533 {
2534 hdd_abort_mac_scan(pHddCtx);
2535 }
2536
2537 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
2538 {
2539 INIT_COMPLETION(pAdapter->session_close_comp_var);
2540 if (eHAL_STATUS_SUCCESS ==
2541 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
2542 hdd_smeCloseSessionCallback, pAdapter))
2543 {
2544 //Block on a completion variable. Can't wait forever though.
2545 wait_for_completion_interruptible_timeout(
2546 &pAdapter->session_close_comp_var,
2547 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2548 }
2549 }
2550
2551 break;
2552
2553 case WLAN_HDD_SOFTAP:
2554 case WLAN_HDD_P2P_GO:
2555 //Any softap specific cleanup here...
2556 mutex_lock(&pHddCtx->sap_lock);
2557 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2558 {
2559 VOS_STATUS status;
2560 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2561
2562 //Stop Bss.
2563 status = WLANSAP_StopBss(pHddCtx->pvosContext);
2564 if (VOS_IS_STATUS_SUCCESS(status))
2565 {
2566 hdd_hostapd_state_t *pHostapdState =
2567 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2568
2569 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2570
2571 if (!VOS_IS_STATUS_SUCCESS(status))
2572 {
2573 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002574 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002575 }
2576 }
2577 else
2578 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002579 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002580 }
2581 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2582
2583 if (eHAL_STATUS_FAILURE ==
2584 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
2585 0, NULL, eANI_BOOLEAN_FALSE))
2586 {
2587 hddLog(LOGE,
2588 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002589 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002590 }
2591
2592 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2593 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2594 eANI_BOOLEAN_FALSE) )
2595 {
2596 hddLog(LOGE,
2597 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
2598 }
2599
2600 // Reset WNI_CFG_PROBE_RSP Flags
2601 wlan_hdd_reset_prob_rspies(pAdapter);
2602 kfree(pAdapter->sessionCtx.ap.beacon);
2603 pAdapter->sessionCtx.ap.beacon = NULL;
2604 }
2605 mutex_unlock(&pHddCtx->sap_lock);
2606 break;
2607 case WLAN_HDD_MONITOR:
2608 break;
2609 default:
2610 break;
2611 }
2612
2613 EXIT();
2614 return VOS_STATUS_SUCCESS;
2615}
2616
2617VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
2618{
2619 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2620 VOS_STATUS status;
2621 hdd_adapter_t *pAdapter;
2622
2623 ENTER();
2624
2625 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2626
2627 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2628 {
2629 pAdapter = pAdapterNode->pAdapter;
2630 netif_tx_disable(pAdapter->dev);
2631 netif_carrier_off(pAdapter->dev);
2632
2633 hdd_stop_adapter( pHddCtx, pAdapter );
2634
2635 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2636 pAdapterNode = pNext;
2637 }
2638
2639 EXIT();
2640
2641 return VOS_STATUS_SUCCESS;
2642}
2643
2644VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
2645{
2646 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2647 VOS_STATUS status;
2648 hdd_adapter_t *pAdapter;
2649
2650 ENTER();
2651
2652 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2653
2654 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2655 {
2656 pAdapter = pAdapterNode->pAdapter;
2657 netif_tx_disable(pAdapter->dev);
2658 netif_carrier_off(pAdapter->dev);
2659
2660 //Record whether STA is associated
2661 pAdapter->sessionCtx.station.bSendDisconnect =
2662 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
2663 VOS_TRUE : VOS_FALSE;
2664
2665 hdd_deinit_tx_rx(pAdapter);
2666 hdd_wmm_adapter_close(pAdapter);
2667
2668 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2669 pAdapterNode = pNext;
2670 }
2671
2672 EXIT();
2673
2674 return VOS_STATUS_SUCCESS;
2675}
2676
2677VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
2678{
2679 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2680 VOS_STATUS status;
2681 hdd_adapter_t *pAdapter;
2682 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
2683
2684 ENTER();
2685
2686 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2687
2688 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2689 {
2690 pAdapter = pAdapterNode->pAdapter;
2691
2692 switch(pAdapter->device_mode)
2693 {
2694 case WLAN_HDD_INFRA_STATION:
2695 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002696 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002697 hdd_init_station_mode(pAdapter);
2698 /* Open the gates for HDD to receive Wext commands */
2699 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002700 pHddCtx->scan_info.mScanPending = FALSE;
2701 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002702
2703 //Trigger the initial scan
2704 hdd_wlan_initial_scan(pAdapter);
2705
2706 //Indicate disconnect event to supplicant if associated previously
2707 if(pAdapter->sessionCtx.station.bSendDisconnect)
2708 {
2709 union iwreq_data wrqu;
2710 memset(&wrqu, '\0', sizeof(wrqu));
2711 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2712 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2713 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2714 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
2715
Jeff Johnson295189b2012-06-20 16:38:30 -07002716 /* indicate disconnected event to nl80211 */
2717 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
2718 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002719 }
2720 break;
2721
2722 case WLAN_HDD_SOFTAP:
2723 /* softAP can handle SSR */
2724 break;
2725
2726 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002727 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
2728 __func__);
2729 /* event supplicant to restart */
2730 cfg80211_del_sta(pAdapter->dev,
2731 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002732 break;
2733
2734 case WLAN_HDD_MONITOR:
2735 /* monitor interface start */
2736 break;
2737 default:
2738 break;
2739 }
2740
2741 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2742 pAdapterNode = pNext;
2743 }
2744
2745 EXIT();
2746
2747 return VOS_STATUS_SUCCESS;
2748}
2749
2750VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
2751{
2752 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2753 hdd_adapter_t *pAdapter;
2754 VOS_STATUS status;
2755 v_U32_t roamId;
2756
2757 ENTER();
2758
2759 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2760
2761 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2762 {
2763 pAdapter = pAdapterNode->pAdapter;
2764
2765 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
2766 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
2767 {
2768 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2769 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2770
2771 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2772 init_completion(&pAdapter->disconnect_comp_var);
2773 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
2774 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2775
2776 wait_for_completion_interruptible_timeout(
2777 &pAdapter->disconnect_comp_var,
2778 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2779
2780 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
2781 pHddCtx->isAmpAllowed = VOS_FALSE;
2782 sme_RoamConnect(pHddCtx->hHal,
2783 pAdapter->sessionId, &(pWextState->roamProfile),
2784 &roamId);
2785 }
2786
2787 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2788 pAdapterNode = pNext;
2789 }
2790
2791 EXIT();
2792
2793 return VOS_STATUS_SUCCESS;
2794}
2795
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07002796void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
2797{
2798 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2799 VOS_STATUS status;
2800 hdd_adapter_t *pAdapter;
2801 hdd_station_ctx_t *pHddStaCtx;
2802 hdd_ap_ctx_t *pHddApCtx;
2803 hdd_hostapd_state_t * pHostapdState;
2804 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
2805 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
2806 const char *p2pMode = "DEV";
2807 const char *ccMode = "Standalone";
2808 int n;
2809
2810 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2811 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2812 {
2813 pAdapter = pAdapterNode->pAdapter;
2814 switch (pAdapter->device_mode) {
2815 case WLAN_HDD_INFRA_STATION:
2816 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2817 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
2818 staChannel = pHddStaCtx->conn_info.operationChannel;
2819 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
2820 }
2821 break;
2822 case WLAN_HDD_P2P_CLIENT:
2823 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2824 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
2825 p2pChannel = pHddStaCtx->conn_info.operationChannel;
2826 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
2827 p2pMode = "CLI";
2828 }
2829 break;
2830 case WLAN_HDD_P2P_GO:
2831 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2832 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2833 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
2834 p2pChannel = pHddApCtx->operatingChannel;
2835 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
2836 }
2837 p2pMode = "GO";
2838 break;
2839 case WLAN_HDD_SOFTAP:
2840 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2841 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2842 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
2843 apChannel = pHddApCtx->operatingChannel;
2844 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
2845 }
2846 break;
2847 default:
2848 break;
2849 }
2850 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2851 pAdapterNode = pNext;
2852 }
2853 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
2854 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
2855 }
2856 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
2857 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
2858 if (p2pChannel > 0) {
2859 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
2860 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
2861 }
2862 if (apChannel > 0) {
2863 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
2864 apChannel, MAC_ADDR_ARRAY(apBssid));
2865 }
2866
2867 if (p2pChannel > 0 && apChannel > 0) {
2868 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
2869 }
2870}
2871
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002872bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07002873{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002874 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07002875}
2876
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002877/* Once SSR is disabled then it cannot be set. */
2878void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07002879{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002880 if (HDD_SSR_DISABLED == isSsrRequired)
2881 return;
2882
Jeff Johnson295189b2012-06-20 16:38:30 -07002883 isSsrRequired = value;
2884}
2885
2886VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
2887 hdd_adapter_list_node_t** ppAdapterNode)
2888{
2889 VOS_STATUS status;
2890 spin_lock(&pHddCtx->hddAdapters.lock);
2891 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
2892 (hdd_list_node_t**) ppAdapterNode );
2893 spin_unlock(&pHddCtx->hddAdapters.lock);
2894 return status;
2895}
2896
2897VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
2898 hdd_adapter_list_node_t* pAdapterNode,
2899 hdd_adapter_list_node_t** pNextAdapterNode)
2900{
2901 VOS_STATUS status;
2902 spin_lock(&pHddCtx->hddAdapters.lock);
2903 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
2904 (hdd_list_node_t*) pAdapterNode,
2905 (hdd_list_node_t**)pNextAdapterNode );
2906
2907 spin_unlock(&pHddCtx->hddAdapters.lock);
2908 return status;
2909}
2910
2911VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
2912 hdd_adapter_list_node_t* pAdapterNode)
2913{
2914 VOS_STATUS status;
2915 spin_lock(&pHddCtx->hddAdapters.lock);
2916 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
2917 &pAdapterNode->node );
2918 spin_unlock(&pHddCtx->hddAdapters.lock);
2919 return status;
2920}
2921
2922VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
2923 hdd_adapter_list_node_t** ppAdapterNode)
2924{
2925 VOS_STATUS status;
2926 spin_lock(&pHddCtx->hddAdapters.lock);
2927 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
2928 (hdd_list_node_t**) ppAdapterNode );
2929 spin_unlock(&pHddCtx->hddAdapters.lock);
2930 return status;
2931}
2932
2933VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
2934 hdd_adapter_list_node_t* pAdapterNode)
2935{
2936 VOS_STATUS status;
2937 spin_lock(&pHddCtx->hddAdapters.lock);
2938 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
2939 (hdd_list_node_t*) pAdapterNode );
2940 spin_unlock(&pHddCtx->hddAdapters.lock);
2941 return status;
2942}
2943
2944VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
2945 hdd_adapter_list_node_t* pAdapterNode)
2946{
2947 VOS_STATUS status;
2948 spin_lock(&pHddCtx->hddAdapters.lock);
2949 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
2950 (hdd_list_node_t*) pAdapterNode );
2951 spin_unlock(&pHddCtx->hddAdapters.lock);
2952 return status;
2953}
2954
2955hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
2956 tSirMacAddr macAddr )
2957{
2958 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2959 hdd_adapter_t *pAdapter;
2960 VOS_STATUS status;
2961
2962 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2963
2964 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2965 {
2966 pAdapter = pAdapterNode->pAdapter;
2967
2968 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
2969 macAddr, sizeof(tSirMacAddr) ) )
2970 {
2971 return pAdapter;
2972 }
2973 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2974 pAdapterNode = pNext;
2975 }
2976
2977 return NULL;
2978
2979}
2980
2981hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
2982{
2983 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2984 hdd_adapter_t *pAdapter;
2985 VOS_STATUS status;
2986
2987 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2988
2989 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2990 {
2991 pAdapter = pAdapterNode->pAdapter;
2992
2993 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
2994 IFNAMSIZ ) )
2995 {
2996 return pAdapter;
2997 }
2998 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2999 pAdapterNode = pNext;
3000 }
3001
3002 return NULL;
3003
3004}
3005
3006hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
3007{
3008 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3009 hdd_adapter_t *pAdapter;
3010 VOS_STATUS status;
3011
3012 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3013
3014 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3015 {
3016 pAdapter = pAdapterNode->pAdapter;
3017
3018 if( pAdapter && (mode == pAdapter->device_mode) )
3019 {
3020 return pAdapter;
3021 }
3022 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3023 pAdapterNode = pNext;
3024 }
3025
3026 return NULL;
3027
3028}
3029
3030//Remove this function later
3031hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
3032{
3033 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3034 hdd_adapter_t *pAdapter;
3035 VOS_STATUS status;
3036
3037 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3038
3039 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3040 {
3041 pAdapter = pAdapterNode->pAdapter;
3042
3043 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
3044 {
3045 return pAdapter;
3046 }
3047
3048 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3049 pAdapterNode = pNext;
3050 }
3051
3052 return NULL;
3053
3054}
3055
Jeff Johnson295189b2012-06-20 16:38:30 -07003056/**---------------------------------------------------------------------------
3057
3058 \brief hdd_set_monitor_tx_adapter() -
3059
3060 This API initializes the adapter to be used while transmitting on monitor
3061 adapter.
3062
3063 \param - pHddCtx - Pointer to the HDD context.
3064 pAdapter - Adapter that will used for TX. This can be NULL.
3065 \return - None.
3066 --------------------------------------------------------------------------*/
3067void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3068{
3069 hdd_adapter_t *pMonAdapter;
3070
3071 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
3072
3073 if( NULL != pMonAdapter )
3074 {
3075 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
3076 }
3077}
Jeff Johnson295189b2012-06-20 16:38:30 -07003078/**---------------------------------------------------------------------------
3079
3080 \brief hdd_select_queue() -
3081
3082 This API returns the operating channel of the requested device mode
3083
3084 \param - pHddCtx - Pointer to the HDD context.
3085 - mode - Device mode for which operating channel is required
3086 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
3087 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
3088 \return - channel number. "0" id the requested device is not found OR it is not connected.
3089 --------------------------------------------------------------------------*/
3090v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
3091{
3092 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3093 VOS_STATUS status;
3094 hdd_adapter_t *pAdapter;
3095 v_U8_t operatingChannel = 0;
3096
3097 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3098
3099 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3100 {
3101 pAdapter = pAdapterNode->pAdapter;
3102
3103 if( mode == pAdapter->device_mode )
3104 {
3105 switch(pAdapter->device_mode)
3106 {
3107 case WLAN_HDD_INFRA_STATION:
3108 case WLAN_HDD_P2P_CLIENT:
3109 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3110 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
3111 break;
3112 case WLAN_HDD_SOFTAP:
3113 case WLAN_HDD_P2P_GO:
3114 /*softap connection info */
3115 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3116 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
3117 break;
3118 default:
3119 break;
3120 }
3121
3122 break; //Found the device of interest. break the loop
3123 }
3124
3125 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3126 pAdapterNode = pNext;
3127 }
3128 return operatingChannel;
3129}
3130
3131#ifdef WLAN_FEATURE_PACKET_FILTERING
3132/**---------------------------------------------------------------------------
3133
3134 \brief hdd_set_multicast_list() -
3135
3136 This used to set the multicast address list.
3137
3138 \param - dev - Pointer to the WLAN device.
3139 - skb - Pointer to OS packet (sk_buff).
3140 \return - success/fail
3141
3142 --------------------------------------------------------------------------*/
3143static void hdd_set_multicast_list(struct net_device *dev)
3144{
3145 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07003146 int mc_count;
3147 int i = 0;
3148 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303149
3150 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07003151 {
3152 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303153 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003154 return;
3155 }
3156
3157 if (dev->flags & IFF_ALLMULTI)
3158 {
3159 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003160 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303161 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003162 }
3163 else
3164 {
3165 mc_count = netdev_mc_count(dev);
3166 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003167 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07003168 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
3169 {
3170 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003171 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303172 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003173 return;
3174 }
3175
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303176 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07003177
3178 netdev_for_each_mc_addr(ha, dev) {
3179 if (i == mc_count)
3180 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303181 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
3182 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
3183 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003184 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303185 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07003186 i++;
3187 }
3188 }
3189 return;
3190}
3191#endif
3192
3193/**---------------------------------------------------------------------------
3194
3195 \brief hdd_select_queue() -
3196
3197 This function is registered with the Linux OS for network
3198 core to decide which queue to use first.
3199
3200 \param - dev - Pointer to the WLAN device.
3201 - skb - Pointer to OS packet (sk_buff).
3202 \return - ac, Queue Index/access category corresponding to UP in IP header
3203
3204 --------------------------------------------------------------------------*/
3205v_U16_t hdd_select_queue(struct net_device *dev,
3206 struct sk_buff *skb)
3207{
3208 return hdd_wmm_select_queue(dev, skb);
3209}
3210
3211
3212/**---------------------------------------------------------------------------
3213
3214 \brief hdd_wlan_initial_scan() -
3215
3216 This function triggers the initial scan
3217
3218 \param - pAdapter - Pointer to the HDD adapter.
3219
3220 --------------------------------------------------------------------------*/
3221void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
3222{
3223 tCsrScanRequest scanReq;
3224 tCsrChannelInfo channelInfo;
3225 eHalStatus halStatus;
3226 unsigned long scanId;
3227 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3228
3229 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
3230 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
3231 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
3232
3233 if(sme_Is11dSupported(pHddCtx->hHal))
3234 {
3235 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
3236 if ( HAL_STATUS_SUCCESS( halStatus ) )
3237 {
3238 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
3239 if( !scanReq.ChannelInfo.ChannelList )
3240 {
3241 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
3242 vos_mem_free(channelInfo.ChannelList);
3243 return;
3244 }
3245 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
3246 channelInfo.numOfChannels);
3247 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
3248 vos_mem_free(channelInfo.ChannelList);
3249 }
3250
3251 scanReq.scanType = eSIR_PASSIVE_SCAN;
3252 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
3253 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
3254 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
3255 }
3256 else
3257 {
3258 scanReq.scanType = eSIR_ACTIVE_SCAN;
3259 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
3260 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
3261 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
3262 }
3263
3264 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
3265 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3266 {
3267 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
3268 __func__, halStatus );
3269 }
3270
3271 if(sme_Is11dSupported(pHddCtx->hHal))
3272 vos_mem_free(scanReq.ChannelInfo.ChannelList);
3273}
3274
3275struct fullPowerContext
3276{
3277 struct completion completion;
3278 unsigned int magic;
3279};
3280#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
3281
3282/**---------------------------------------------------------------------------
3283
3284 \brief hdd_full_power_callback() - HDD full power callback function
3285
3286 This is the function invoked by SME to inform the result of a full power
3287 request issued by HDD
3288
3289 \param - callbackcontext - Pointer to cookie
3290 \param - status - result of request
3291
3292 \return - None
3293
3294 --------------------------------------------------------------------------*/
3295static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
3296{
3297 struct fullPowerContext *pContext = callbackContext;
3298
3299 hddLog(VOS_TRACE_LEVEL_INFO,
3300 "%s: context = %p, status = %d", pContext, status);
3301
3302 if (NULL == callbackContext)
3303 {
3304 hddLog(VOS_TRACE_LEVEL_ERROR,
3305 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003306 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07003307 return;
3308 }
3309
3310 /* there is a race condition that exists between this callback function
3311 and the caller since the caller could time out either before or
3312 while this code is executing. we'll assume the timeout hasn't
3313 occurred, but we'll verify that right before we save our work */
3314
3315 if (POWER_CONTEXT_MAGIC != pContext->magic)
3316 {
3317 /* the caller presumably timed out so there is nothing we can do */
3318 hddLog(VOS_TRACE_LEVEL_WARN,
3319 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003320 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07003321 return;
3322 }
3323
3324 /* the race is on. caller could have timed out immediately after
3325 we verified the magic, but if so, caller will wait a short time
3326 for us to notify the caller, so the context will stay valid */
3327 complete(&pContext->completion);
3328}
3329
3330/**---------------------------------------------------------------------------
3331
3332 \brief hdd_wlan_exit() - HDD WLAN exit function
3333
3334 This is the driver exit point (invoked during rmmod)
3335
3336 \param - pHddCtx - Pointer to the HDD Context
3337
3338 \return - None
3339
3340 --------------------------------------------------------------------------*/
3341void hdd_wlan_exit(hdd_context_t *pHddCtx)
3342{
3343 eHalStatus halStatus;
3344 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
3345 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05303346 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003347 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003348 struct fullPowerContext powerContext;
3349 long lrc;
3350
3351 ENTER();
3352
Jeff Johnson88ba7742013-02-27 14:36:02 -08003353 if (VOS_FTM_MODE != hdd_get_conparam())
3354 {
3355 // Unloading, restart logic is no more required.
3356 wlan_hdd_restart_deinit(pHddCtx);
3357 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003358
Jeff Johnson295189b2012-06-20 16:38:30 -07003359 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003360 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003361 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003362 {
3363 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
3364 WLAN_HDD_INFRA_STATION);
3365 if (pAdapter == NULL)
3366 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3367
3368 if (pAdapter != NULL)
3369 {
3370 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
3371 hdd_UnregisterWext(pAdapter->dev);
3372 }
3373 }
3374 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003375
Jeff Johnson295189b2012-06-20 16:38:30 -07003376 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08003377 {
3378 wlan_hdd_ftm_close(pHddCtx);
3379 goto free_hdd_ctx;
3380 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003381 //Stop the Interface TX queue.
3382 //netif_tx_disable(pWlanDev);
3383 //netif_carrier_off(pWlanDev);
3384
Jeff Johnson295189b2012-06-20 16:38:30 -07003385 if (VOS_STA_SAP_MODE == hdd_get_conparam())
3386 {
3387 pAdapter = hdd_get_adapter(pHddCtx,
3388 WLAN_HDD_SOFTAP);
3389 }
3390 else
3391 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003392 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003393 {
3394 pAdapter = hdd_get_adapter(pHddCtx,
3395 WLAN_HDD_INFRA_STATION);
3396 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003397 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003398 /* DeRegister with platform driver as client for Suspend/Resume */
3399 vosStatus = hddDeregisterPmOps(pHddCtx);
3400 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3401 {
3402 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
3403 VOS_ASSERT(0);
3404 }
3405
3406 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
3407 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3408 {
3409 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
3410 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003411
3412 // Cancel any outstanding scan requests. We are about to close all
3413 // of our adapters, but an adapter structure is what SME passes back
3414 // to our callback function. Hence if there are any outstanding scan
3415 // requests then there is a race condition between when the adapter
3416 // is closed and when the callback is invoked. We try to resolve that
3417 // race condition here by canceling any outstanding scans before we
3418 // close the adapters.
3419 // Note that the scans may be cancelled in an asynchronous manner, so
3420 // ideally there needs to be some kind of synchronization. Rather than
3421 // introduce a new synchronization here, we will utilize the fact that
3422 // we are about to Request Full Power, and since that is synchronized,
3423 // the expectation is that by the time Request Full Power has completed,
3424 // all scans will be cancelled.
3425 hdd_abort_mac_scan( pHddCtx );
3426
3427 //Disable IMPS/BMPS as we do not want the device to enter any power
3428 //save mode during shutdown
3429 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3430 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3431 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
3432
3433 //Ensure that device is in full power as we will touch H/W during vos_Stop
3434 init_completion(&powerContext.completion);
3435 powerContext.magic = POWER_CONTEXT_MAGIC;
3436
3437 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
3438 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
3439
3440 if (eHAL_STATUS_SUCCESS != halStatus)
3441 {
3442 if (eHAL_STATUS_PMC_PENDING == halStatus)
3443 {
3444 /* request was sent -- wait for the response */
3445 lrc = wait_for_completion_interruptible_timeout(
3446 &powerContext.completion,
3447 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
3448 /* either we have a response or we timed out
3449 either way, first invalidate our magic */
3450 powerContext.magic = 0;
3451 if (lrc <= 0)
3452 {
3453 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003454 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07003455 /* there is a race condition such that the callback
3456 function could be executing at the same time we are. of
3457 primary concern is if the callback function had already
3458 verified the "magic" but hasn't yet set the completion
3459 variable. Since the completion variable is on our
3460 stack, we'll delay just a bit to make sure the data is
3461 still valid if that is the case */
3462 msleep(50);
3463 }
3464 }
3465 else
3466 {
3467 hddLog(VOS_TRACE_LEVEL_ERROR,
3468 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003469 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07003470 VOS_ASSERT(0);
3471 /* continue -- need to clean up as much as possible */
3472 }
3473 }
3474
3475 // Unregister the Net Device Notifier
3476 unregister_netdevice_notifier(&hdd_netdev_notifier);
3477
Jeff Johnson295189b2012-06-20 16:38:30 -07003478 hdd_stop_all_adapters( pHddCtx );
3479
Jeff Johnson295189b2012-06-20 16:38:30 -07003480#ifdef WLAN_BTAMP_FEATURE
3481 vosStatus = WLANBAP_Stop(pVosContext);
3482 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3483 {
3484 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3485 "%s: Failed to stop BAP",__func__);
3486 }
3487#endif //WLAN_BTAMP_FEATURE
3488
3489 //Stop all the modules
3490 vosStatus = vos_stop( pVosContext );
3491 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3492 {
3493 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3494 "%s: Failed to stop VOSS",__func__);
3495 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3496 }
3497
Jeff Johnson295189b2012-06-20 16:38:30 -07003498 //Assert Deep sleep signal now to put Libra HW in lowest power state
3499 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
3500 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3501
3502 //Vote off any PMIC voltage supplies
3503 vos_chipPowerDown(NULL, NULL, NULL);
3504
3505 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
3506
3507 //Clean up HDD Nlink Service
3508 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
3509 nl_srv_exit();
3510
3511 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07003512 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003513
3514 //Close the scheduler before calling vos_close to make sure no thread is
3515 // scheduled after the each module close is called i.e after all the data
3516 // structures are freed.
3517 vosStatus = vos_sched_close( pVosContext );
3518 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
3519 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
3520 "%s: Failed to close VOSS Scheduler",__func__);
3521 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3522 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003523#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07003524#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3525 /* Destroy the wake lock */
3526 wake_lock_destroy(&pHddCtx->rx_wake_lock);
3527#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08003528 /* Destroy the wake lock */
3529 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003530#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003531
3532 //Close VOSS
3533 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
3534 vos_close(pVosContext);
3535
Jeff Johnson295189b2012-06-20 16:38:30 -07003536 //Close Watchdog
3537 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3538 vos_watchdog_close(pVosContext);
3539
3540 /* Cancel the vote for XO Core ON.
3541 * This is done here to ensure there is no race condition since MC, TX and WD threads have
3542 * exited at this point
3543 */
3544 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
3545 " when WLAN is turned OFF\n");
3546 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
3547 {
3548 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
3549 " Not returning failure."
3550 " Power consumed will be high\n");
3551 }
3552
3553 hdd_close_all_adapters( pHddCtx );
3554
3555
3556 //Free up dynamically allocated members inside HDD Adapter
3557 kfree(pHddCtx->cfg_ini);
3558 pHddCtx->cfg_ini= NULL;
3559
3560 /* free the power on lock from platform driver */
3561 if (free_riva_power_on_lock("wlan"))
3562 {
3563 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
3564 __func__);
3565 }
3566
Jeff Johnson88ba7742013-02-27 14:36:02 -08003567free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08003568 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07003569 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07003570 if (hdd_is_ssr_required())
3571 {
3572 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07003573 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07003574 msleep(5000);
3575 }
3576 hdd_set_ssr_required (VOS_FALSE);
3577}
3578
3579
3580/**---------------------------------------------------------------------------
3581
3582 \brief hdd_update_config_from_nv() - Function to update the contents of
3583 the running configuration with parameters taken from NV storage
3584
3585 \param - pHddCtx - Pointer to the HDD global context
3586
3587 \return - VOS_STATUS_SUCCESS if successful
3588
3589 --------------------------------------------------------------------------*/
3590static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
3591{
Jeff Johnson295189b2012-06-20 16:38:30 -07003592 v_BOOL_t itemIsValid = VOS_FALSE;
3593 VOS_STATUS status;
3594 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
3595 v_U8_t macLoop;
3596
3597 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
3598 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
3599 if(status != VOS_STATUS_SUCCESS)
3600 {
3601 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
3602 return VOS_STATUS_E_FAILURE;
3603 }
3604
3605 if (itemIsValid == VOS_TRUE)
3606 {
3607 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
3608 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
3609 VOS_MAX_CONCURRENCY_PERSONA);
3610 if(status != VOS_STATUS_SUCCESS)
3611 {
3612 /* Get MAC from NV fail, not update CFG info
3613 * INI MAC value will be used for MAC setting */
3614 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
3615 return VOS_STATUS_E_FAILURE;
3616 }
3617
3618 /* If first MAC is not valid, treat all others are not valid
3619 * Then all MACs will be got from ini file */
3620 if(vos_is_macaddr_zero(&macFromNV[0]))
3621 {
3622 /* MAC address in NV file is not configured yet */
3623 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
3624 return VOS_STATUS_E_INVAL;
3625 }
3626
3627 /* Get MAC address from NV, update CFG info */
3628 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
3629 {
3630 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
3631 {
3632 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
3633 /* This MAC is not valid, skip it
3634 * This MAC will be got from ini file */
3635 }
3636 else
3637 {
3638 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
3639 (v_U8_t *)&macFromNV[macLoop].bytes[0],
3640 VOS_MAC_ADDR_SIZE);
3641 }
3642 }
3643 }
3644 else
3645 {
3646 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
3647 return VOS_STATUS_E_FAILURE;
3648 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003649
Jeff Johnson295189b2012-06-20 16:38:30 -07003650
3651 return VOS_STATUS_SUCCESS;
3652}
3653
3654/**---------------------------------------------------------------------------
3655
3656 \brief hdd_post_voss_start_config() - HDD post voss start config helper
3657
3658 \param - pAdapter - Pointer to the HDD
3659
3660 \return - None
3661
3662 --------------------------------------------------------------------------*/
3663VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
3664{
3665 eHalStatus halStatus;
3666 v_U32_t listenInterval;
3667
Jeff Johnson295189b2012-06-20 16:38:30 -07003668
3669 // Send ready indication to the HDD. This will kick off the MAC
3670 // into a 'running' state and should kick off an initial scan.
3671 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
3672 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3673 {
3674 hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
3675 "code %08d [x%08x]",__func__, halStatus, halStatus );
3676 return VOS_STATUS_E_FAILURE;
3677 }
3678
3679 // Set default LI into HDD context,
3680 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
3681 // And RIVA will crash
3682 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
3683 pHddCtx->hdd_actual_LI_value = listenInterval;
3684
3685 return VOS_STATUS_SUCCESS;
3686}
3687
Jeff Johnson295189b2012-06-20 16:38:30 -07003688/* wake lock APIs for HDD */
3689void hdd_prevent_suspend(void)
3690{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003691#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003692 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003693#else
3694 wcnss_prevent_suspend();
3695#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003696}
3697
3698void hdd_allow_suspend(void)
3699{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003700#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003701 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003702#else
3703 wcnss_allow_suspend();
3704#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003705}
3706
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003707void hdd_allow_suspend_timeout(v_U32_t timeout)
3708{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003709#ifdef WLAN_OPEN_SOURCE
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003710 wake_lock_timeout(&wlan_wake_lock, timeout);
3711#else
3712 /* Do nothing as there is no API in wcnss for timeout*/
3713#endif
3714}
3715
Jeff Johnson295189b2012-06-20 16:38:30 -07003716/**---------------------------------------------------------------------------
3717
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003718 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
3719 information between Host and Riva
3720
3721 This function gets reported version of FW
3722 It also finds the version of Riva headers used to compile the host
3723 It compares the above two and prints a warning if they are different
3724 It gets the SW and HW version string
3725 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
3726 indicating the features they support through a bitmap
3727
3728 \param - pHddCtx - Pointer to HDD context
3729
3730 \return - void
3731
3732 --------------------------------------------------------------------------*/
3733
3734void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
3735{
3736
3737 tSirVersionType versionCompiled;
3738 tSirVersionType versionReported;
3739 tSirVersionString versionString;
3740 tANI_U8 fwFeatCapsMsgSupported = 0;
3741 VOS_STATUS vstatus;
3742
3743 /* retrieve and display WCNSS version information */
3744 do {
3745
3746 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
3747 &versionCompiled);
3748 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3749 {
3750 hddLog(VOS_TRACE_LEVEL_FATAL,
3751 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003752 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003753 break;
3754 }
3755
3756 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
3757 &versionReported);
3758 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3759 {
3760 hddLog(VOS_TRACE_LEVEL_FATAL,
3761 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003762 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003763 break;
3764 }
3765
3766 if ((versionCompiled.major != versionReported.major) ||
3767 (versionCompiled.minor != versionReported.minor) ||
3768 (versionCompiled.version != versionReported.version) ||
3769 (versionCompiled.revision != versionReported.revision))
3770 {
3771 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
3772 "Host expected %u.%u.%u.%u\n",
3773 WLAN_MODULE_NAME,
3774 (int)versionReported.major,
3775 (int)versionReported.minor,
3776 (int)versionReported.version,
3777 (int)versionReported.revision,
3778 (int)versionCompiled.major,
3779 (int)versionCompiled.minor,
3780 (int)versionCompiled.version,
3781 (int)versionCompiled.revision);
3782 }
3783 else
3784 {
3785 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
3786 WLAN_MODULE_NAME,
3787 (int)versionReported.major,
3788 (int)versionReported.minor,
3789 (int)versionReported.version,
3790 (int)versionReported.revision);
3791 }
3792
3793 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
3794 versionString,
3795 sizeof(versionString));
3796 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3797 {
3798 hddLog(VOS_TRACE_LEVEL_FATAL,
3799 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003800 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003801 break;
3802 }
3803
3804 pr_info("%s: WCNSS software version %s\n",
3805 WLAN_MODULE_NAME, versionString);
3806
3807 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
3808 versionString,
3809 sizeof(versionString));
3810 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3811 {
3812 hddLog(VOS_TRACE_LEVEL_FATAL,
3813 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003814 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003815 break;
3816 }
3817
3818 pr_info("%s: WCNSS hardware version %s\n",
3819 WLAN_MODULE_NAME, versionString);
3820
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003821 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
3822 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003823 send the message only if it the riva is 1.1
3824 minor numbers for different riva branches:
3825 0 -> (1.0)Mainline Build
3826 1 -> (1.1)Mainline Build
3827 2->(1.04) Stability Build
3828 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003829 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003830 ((versionReported.minor>=1) && (versionReported.version>=1)))
3831 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
3832 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003833
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003834 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08003835 {
3836#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
3837 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
3838 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
3839#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003840 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08003841 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003842
3843 } while (0);
3844
3845}
3846
3847/**---------------------------------------------------------------------------
3848
Jeff Johnson295189b2012-06-20 16:38:30 -07003849 \brief hdd_wlan_startup() - HDD init function
3850
3851 This is the driver startup code executed once a WLAN device has been detected
3852
3853 \param - dev - Pointer to the underlying device
3854
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003855 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07003856
3857 --------------------------------------------------------------------------*/
3858
3859int hdd_wlan_startup(struct device *dev )
3860{
3861 VOS_STATUS status;
3862 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003863 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003864 hdd_context_t *pHddCtx = NULL;
3865 v_CONTEXT_t pVosContext= NULL;
3866#ifdef WLAN_BTAMP_FEATURE
3867 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
3868 WLANBAP_ConfigType btAmpConfig;
3869 hdd_config_t *pConfig;
3870#endif
3871 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07003872 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003873
3874 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07003875 /*
3876 * cfg80211: wiphy allocation
3877 */
3878 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
3879
3880 if(wiphy == NULL)
3881 {
3882 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003883 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003884 }
3885
3886 pHddCtx = wiphy_priv(wiphy);
3887
Jeff Johnson295189b2012-06-20 16:38:30 -07003888 //Initialize the adapter context to zeros.
3889 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
3890
Jeff Johnson295189b2012-06-20 16:38:30 -07003891 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003892 hdd_prevent_suspend();
3893 pHddCtx->isLoadUnloadInProgress = TRUE;
3894
3895 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
3896
3897 /*Get vos context here bcoz vos_open requires it*/
3898 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
3899
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08003900 if(pVosContext == NULL)
3901 {
3902 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
3903 goto err_free_hdd_context;
3904 }
3905
Jeff Johnson295189b2012-06-20 16:38:30 -07003906 //Save the Global VOSS context in adapter context for future.
3907 pHddCtx->pvosContext = pVosContext;
3908
3909 //Save the adapter context in global context for future.
3910 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
3911
Jeff Johnson295189b2012-06-20 16:38:30 -07003912 pHddCtx->parent_dev = dev;
3913
3914 init_completion(&pHddCtx->full_pwr_comp_var);
3915 init_completion(&pHddCtx->standby_comp_var);
3916 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003917 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003918 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003919
3920 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
3921
3922 // Load all config first as TL config is needed during vos_open
3923 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
3924 if(pHddCtx->cfg_ini == NULL)
3925 {
3926 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
3927 goto err_free_hdd_context;
3928 }
3929
3930 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
3931
3932 // Read and parse the qcom_cfg.ini file
3933 status = hdd_parse_config_ini( pHddCtx );
3934 if ( VOS_STATUS_SUCCESS != status )
3935 {
3936 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
3937 __func__, WLAN_INI_FILE);
3938 goto err_config;
3939 }
3940
Jeff Johnson295189b2012-06-20 16:38:30 -07003941 /*
3942 * cfg80211: Initialization and registration ...
3943 */
3944 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
3945 {
3946 hddLog(VOS_TRACE_LEVEL_FATAL,
3947 "%s: wlan_hdd_cfg80211_register return failure", __func__);
3948 goto err_wiphy_reg;
3949 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003950
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003951 // Update VOS trace levels based upon the cfg.ini
3952 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
3953 pHddCtx->cfg_ini->vosTraceEnableBAP);
3954 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
3955 pHddCtx->cfg_ini->vosTraceEnableTL);
3956 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
3957 pHddCtx->cfg_ini->vosTraceEnableWDI);
3958 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
3959 pHddCtx->cfg_ini->vosTraceEnableHDD);
3960 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
3961 pHddCtx->cfg_ini->vosTraceEnableSME);
3962 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
3963 pHddCtx->cfg_ini->vosTraceEnablePE);
3964 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
3965 pHddCtx->cfg_ini->vosTraceEnableWDA);
3966 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
3967 pHddCtx->cfg_ini->vosTraceEnableSYS);
3968 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
3969 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003970 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
3971 pHddCtx->cfg_ini->vosTraceEnableSAP);
3972 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
3973 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003974
Jeff Johnson295189b2012-06-20 16:38:30 -07003975 // Update WDI trace levels based upon the cfg.ini
3976 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
3977 pHddCtx->cfg_ini->wdiTraceEnableDAL);
3978 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
3979 pHddCtx->cfg_ini->wdiTraceEnableCTL);
3980 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
3981 pHddCtx->cfg_ini->wdiTraceEnableDAT);
3982 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
3983 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003984
Jeff Johnson88ba7742013-02-27 14:36:02 -08003985 if (VOS_FTM_MODE == hdd_get_conparam())
3986 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003987 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
3988 {
3989 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
3990 goto err_free_hdd_context;
3991 }
3992 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
3993 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08003994 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003995
Jeff Johnson88ba7742013-02-27 14:36:02 -08003996 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07003997 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3998 {
3999 status = vos_watchdog_open(pVosContext,
4000 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
4001
4002 if(!VOS_IS_STATUS_SUCCESS( status ))
4003 {
4004 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004005 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07004006 }
4007 }
4008
4009 pHddCtx->isLogpInProgress = FALSE;
4010 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4011
Jeff Johnson295189b2012-06-20 16:38:30 -07004012 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
4013 if(!VOS_IS_STATUS_SUCCESS(status))
4014 {
4015 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004016 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004017 }
4018
Jeff Johnson295189b2012-06-20 16:38:30 -07004019 status = vos_open( &pVosContext, 0);
4020 if ( !VOS_IS_STATUS_SUCCESS( status ))
4021 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004022 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
4023 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07004024 }
4025
Jeff Johnson295189b2012-06-20 16:38:30 -07004026 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
4027
4028 if ( NULL == pHddCtx->hHal )
4029 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004030 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004031 goto err_vosclose;
4032 }
4033
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004034 status = vos_preStart( pHddCtx->pvosContext );
4035 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4036 {
4037 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
4038 goto err_vosclose;
4039 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004040
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004041 /* Note that the vos_preStart() sequence triggers the cfg download.
4042 The cfg download must occur before we update the SME config
4043 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07004044 status = hdd_set_sme_config( pHddCtx );
4045
4046 if ( VOS_STATUS_SUCCESS != status )
4047 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004048 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
4049 goto err_vosclose;
4050 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004051
4052 //Initialize the WMM module
4053 status = hdd_wmm_init(pHddCtx);
4054 if (!VOS_IS_STATUS_SUCCESS(status))
4055 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004056 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004057 goto err_vosclose;
4058 }
4059
Jeff Johnson295189b2012-06-20 16:38:30 -07004060 /* In the integrated architecture we update the configuration from
4061 the INI file and from NV before vOSS has been started so that
4062 the final contents are available to send down to the cCPU */
4063
4064 // Apply the cfg.ini to cfg.dat
4065 if (FALSE == hdd_update_config_dat(pHddCtx))
4066 {
4067 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
4068 goto err_vosclose;
4069 }
4070
4071 // Apply the NV to cfg.dat
4072 /* Prima Update MAC address only at here */
4073 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
4074 {
4075#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
4076 /* There was not a valid set of MAC Addresses in NV. See if the
4077 default addresses were modified by the cfg.ini settings. If so,
4078 we'll use them, but if not, we'll autogenerate a set of MAC
4079 addresses based upon the device serial number */
4080
4081 static const v_MACADDR_t default_address =
4082 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
4083 unsigned int serialno;
4084 int i;
4085
4086 serialno = wcnss_get_serial_number();
4087 if ((0 != serialno) &&
4088 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
4089 sizeof(default_address))))
4090 {
4091 /* cfg.ini has the default address, invoke autogen logic */
4092
4093 /* MAC address has 3 bytes of OUI so we have a maximum of 3
4094 bytes of the serial number that can be used to generate
4095 the other 3 bytes of the MAC address. Mask off all but
4096 the lower 3 bytes (this will also make sure we don't
4097 overflow in the next step) */
4098 serialno &= 0x00FFFFFF;
4099
4100 /* we need a unique address for each session */
4101 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
4102
4103 /* autogen all addresses */
4104 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4105 {
4106 /* start with the entire default address */
4107 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
4108 /* then replace the lower 3 bytes */
4109 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
4110 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
4111 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
4112
4113 serialno++;
4114 }
4115
4116 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
4117 MAC_ADDRESS_STR,
4118 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4119 }
4120 else
4121#endif //WLAN_AUTOGEN_MACADDR_FEATURE
4122 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004123 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004124 "%s: Invalid MAC address in NV, using MAC from ini file "
4125 MAC_ADDRESS_STR, __func__,
4126 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4127 }
4128 }
4129 {
4130 eHalStatus halStatus;
4131 // Set the MAC Address
4132 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
4133 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
4134 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
4135 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
4136
4137 if (!HAL_STATUS_SUCCESS( halStatus ))
4138 {
4139 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
4140 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08004141 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004142 }
4143 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004144
4145 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
4146 Note: Firmware image will be read and downloaded inside vos_start API */
4147 status = vos_start( pHddCtx->pvosContext );
4148 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4149 {
4150 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
4151 goto err_vosclose;
4152 }
4153
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004154 /* Exchange capability info between Host and FW and also get versioning info from FW */
4155 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004156
4157 status = hdd_post_voss_start_config( pHddCtx );
4158 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4159 {
4160 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
4161 __func__);
4162 goto err_vosstop;
4163 }
4164
Jeff Johnson295189b2012-06-20 16:38:30 -07004165 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4166 {
4167 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
4168 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4169 }
4170 else
4171 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004172 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
4173 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4174 if (pAdapter != NULL)
4175 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304176 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07004177 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304178 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
4179 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
4180 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07004181
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304182 /* Generate the P2P Device Address. This consists of the device's
4183 * primary MAC address with the locally administered bit set.
4184 */
4185 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07004186 }
4187 else
4188 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304189 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
4190 if (p2p_dev_addr != NULL)
4191 {
4192 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
4193 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
4194 }
4195 else
4196 {
4197 hddLog(VOS_TRACE_LEVEL_FATAL,
4198 "%s: Failed to allocate mac_address for p2p_device",
4199 __func__);
4200 goto err_close_adapter;
4201 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004202 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004203
4204 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
4205 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
4206 if ( NULL == pP2pAdapter )
4207 {
4208 hddLog(VOS_TRACE_LEVEL_FATAL,
4209 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004210 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004211 goto err_close_adapter;
4212 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004213 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004214 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004215
4216 if( pAdapter == NULL )
4217 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004218 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
4219 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004220 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004221
Jeff Johnson295189b2012-06-20 16:38:30 -07004222#ifdef WLAN_BTAMP_FEATURE
4223 vStatus = WLANBAP_Open(pVosContext);
4224 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4225 {
4226 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4227 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004228 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004229 }
4230
4231 vStatus = BSL_Init(pVosContext);
4232 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4233 {
4234 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4235 "%s: Failed to Init BSL",__func__);
4236 goto err_bap_close;
4237 }
4238 vStatus = WLANBAP_Start(pVosContext);
4239 if (!VOS_IS_STATUS_SUCCESS(vStatus))
4240 {
4241 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4242 "%s: Failed to start TL",__func__);
4243 goto err_bap_close;
4244 }
4245
4246 pConfig = pHddCtx->cfg_ini;
4247 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
4248 status = WLANBAP_SetConfig(&btAmpConfig);
4249
4250#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07004251
Jeff Johnson295189b2012-06-20 16:38:30 -07004252#ifdef FEATURE_WLAN_SCAN_PNO
4253 /*SME must send channel update configuration to RIVA*/
4254 sme_UpdateChannelConfig(pHddCtx->hHal);
4255#endif
4256
Jeff Johnson295189b2012-06-20 16:38:30 -07004257 /* Register with platform driver as client for Suspend/Resume */
4258 status = hddRegisterPmOps(pHddCtx);
4259 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4260 {
4261 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
4262#ifdef WLAN_BTAMP_FEATURE
4263 goto err_bap_stop;
4264#else
Jeff Johnsone7245742012-09-05 17:12:55 -07004265 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004266#endif //WLAN_BTAMP_FEATURE
4267 }
4268
4269 /* Register TM level change handler function to the platform */
4270 status = hddDevTmRegisterNotifyCallback(pHddCtx);
4271 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4272 {
4273 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
4274 goto err_unregister_pmops;
4275 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004276
4277 /* register for riva power on lock to platform driver */
4278 if (req_riva_power_on_lock("wlan"))
4279 {
4280 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
4281 __func__);
4282 goto err_unregister_pmops;
4283 }
4284
Jeff Johnson295189b2012-06-20 16:38:30 -07004285 // register net device notifier for device change notification
4286 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4287
4288 if(ret < 0)
4289 {
4290 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
4291 goto err_free_power_on_lock;
4292 }
4293
4294 //Initialize the nlink service
4295 if(nl_srv_init() != 0)
4296 {
4297 hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
4298 goto err_reg_netdev;
4299 }
4300
4301 //Initialize the BTC service
4302 if(btc_activate_service(pHddCtx) != 0)
4303 {
4304 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
4305 goto err_nl_srv;
4306 }
4307
4308#ifdef PTT_SOCK_SVC_ENABLE
4309 //Initialize the PTT service
4310 if(ptt_sock_activate_svc(pHddCtx) != 0)
4311 {
4312 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
4313 goto err_nl_srv;
4314 }
4315#endif
4316
Jeff Johnson295189b2012-06-20 16:38:30 -07004317 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004318 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004319 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07004320 /* Action frame registered in one adapter which will
4321 * applicable to all interfaces
4322 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07004323 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07004324 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004325
4326 mutex_init(&pHddCtx->sap_lock);
4327
4328 pHddCtx->isLoadUnloadInProgress = FALSE;
4329
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004330#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004331#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4332 /* Initialize the wake lcok */
4333 wake_lock_init(&pHddCtx->rx_wake_lock,
4334 WAKE_LOCK_SUSPEND,
4335 "qcom_rx_wakelock");
4336#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004337 /* Initialize the wake lcok */
4338 wake_lock_init(&pHddCtx->sap_wake_lock,
4339 WAKE_LOCK_SUSPEND,
4340 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004341#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004342
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004343 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
4344 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07004345
4346 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4347 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004348
4349 // Initialize the restart logic
4350 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05304351
Jeff Johnson295189b2012-06-20 16:38:30 -07004352 goto success;
4353
4354err_nl_srv:
4355 nl_srv_exit();
4356
4357err_reg_netdev:
4358 unregister_netdevice_notifier(&hdd_netdev_notifier);
4359
4360err_free_power_on_lock:
4361 free_riva_power_on_lock("wlan");
4362
4363err_unregister_pmops:
4364 hddDevTmUnregisterNotifyCallback(pHddCtx);
4365 hddDeregisterPmOps(pHddCtx);
4366
4367#ifdef WLAN_BTAMP_FEATURE
4368err_bap_stop:
4369 WLANBAP_Stop(pVosContext);
4370#endif
4371
4372#ifdef WLAN_BTAMP_FEATURE
4373err_bap_close:
4374 WLANBAP_Close(pVosContext);
4375#endif
4376
Jeff Johnson295189b2012-06-20 16:38:30 -07004377err_close_adapter:
4378 hdd_close_all_adapters( pHddCtx );
4379
4380err_vosstop:
4381 vos_stop(pVosContext);
4382
4383err_vosclose:
4384 status = vos_sched_close( pVosContext );
4385 if (!VOS_IS_STATUS_SUCCESS(status)) {
4386 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4387 "%s: Failed to close VOSS Scheduler", __func__);
4388 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
4389 }
4390 vos_close(pVosContext );
4391
Jeff Johnson295189b2012-06-20 16:38:30 -07004392err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004393 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004394
4395err_wdclose:
4396 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4397 vos_watchdog_close(pVosContext);
4398
Jeff Johnson295189b2012-06-20 16:38:30 -07004399err_wiphy_reg:
4400 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004401
4402err_config:
4403 kfree(pHddCtx->cfg_ini);
4404 pHddCtx->cfg_ini= NULL;
4405
4406err_free_hdd_context:
4407 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004408 wiphy_free(wiphy) ;
4409 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004410 VOS_BUG(1);
4411
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08004412 if (hdd_is_ssr_required())
4413 {
4414 /* WDI timeout had happened during load, so SSR is needed here */
4415 subsystem_restart("wcnss");
4416 msleep(5000);
4417 }
4418 hdd_set_ssr_required (VOS_FALSE);
4419
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004420 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004421
4422success:
4423 EXIT();
4424 return 0;
4425}
4426
4427/**---------------------------------------------------------------------------
4428
Jeff Johnson32d95a32012-09-10 13:15:23 -07004429 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07004430
Jeff Johnson32d95a32012-09-10 13:15:23 -07004431 This is the driver entry point - called in different timeline depending
4432 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07004433
4434 \param - None
4435
4436 \return - 0 for success, non zero for failure
4437
4438 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07004439static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004440{
4441 VOS_STATUS status;
4442 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004443 struct device *dev = NULL;
4444 int ret_status = 0;
4445
4446 ENTER();
4447
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004448#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004449 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07004450#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004451
4452 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
4453 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
4454
4455 //Power Up Libra WLAN card first if not already powered up
4456 status = vos_chipPowerUp(NULL,NULL,NULL);
4457 if (!VOS_IS_STATUS_SUCCESS(status))
4458 {
4459 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
4460 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004461 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004462 }
4463
Jeff Johnson295189b2012-06-20 16:38:30 -07004464#ifdef ANI_BUS_TYPE_PCI
4465
4466 dev = wcnss_wlan_get_device();
4467
4468#endif // ANI_BUS_TYPE_PCI
4469
4470#ifdef ANI_BUS_TYPE_PLATFORM
4471 dev = wcnss_wlan_get_device();
4472#endif // ANI_BUS_TYPE_PLATFORM
4473
4474
4475 do {
4476 if (NULL == dev) {
4477 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
4478 ret_status = -1;
4479 break;
4480 }
4481
4482#ifdef MEMORY_DEBUG
4483 vos_mem_init();
4484#endif
4485
4486#ifdef TIMER_MANAGER
4487 vos_timer_manager_init();
4488#endif
4489
4490 /* Preopen VOSS so that it is ready to start at least SAL */
4491 status = vos_preOpen(&pVosContext);
4492
4493 if (!VOS_IS_STATUS_SUCCESS(status))
4494 {
4495 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
4496 ret_status = -1;
4497 break;
4498 }
4499
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004500#ifndef MODULE
4501 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
4502 */
4503 hdd_set_conparam((v_UINT_t)con_mode);
4504#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004505
4506 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004507 if (hdd_wlan_startup(dev))
4508 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004509 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004510 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004511 vos_preClose( &pVosContext );
4512 ret_status = -1;
4513 break;
4514 }
4515
4516 /* Cancel the vote for XO Core ON
4517 * This is done here for safety purposes in case we re-initialize without turning
4518 * it OFF in any error scenario.
4519 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004520 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07004521 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004522 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07004523 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4524 {
4525 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
4526 " Power consumed will be high\n");
4527 }
4528 } while (0);
4529
4530 if (0 != ret_status)
4531 {
4532 //Assert Deep sleep signal now to put Libra HW in lowest power state
4533 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4534 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
4535
4536 //Vote off any PMIC voltage supplies
4537 vos_chipPowerDown(NULL, NULL, NULL);
4538#ifdef TIMER_MANAGER
4539 vos_timer_exit();
4540#endif
4541#ifdef MEMORY_DEBUG
4542 vos_mem_exit();
4543#endif
4544
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004545#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004546 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004547#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004548 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
4549 }
4550 else
4551 {
4552 //Send WLAN UP indication to Nlink Service
4553 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
4554
4555 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
4556
4557 }
4558
4559 EXIT();
4560
4561 return ret_status;
4562}
4563
Jeff Johnson32d95a32012-09-10 13:15:23 -07004564/**---------------------------------------------------------------------------
4565
4566 \brief hdd_module_init() - Init Function
4567
4568 This is the driver entry point (invoked when module is loaded using insmod)
4569
4570 \param - None
4571
4572 \return - 0 for success, non zero for failure
4573
4574 --------------------------------------------------------------------------*/
4575#ifdef MODULE
4576static int __init hdd_module_init ( void)
4577{
4578 return hdd_driver_init();
4579}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004580#else /* #ifdef MODULE */
4581static int __init hdd_module_init ( void)
4582{
4583 /* Driver initialization is delayed to fwpath_changed_handler */
4584 return 0;
4585}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004586#endif /* #ifdef MODULE */
4587
Jeff Johnson295189b2012-06-20 16:38:30 -07004588
4589/**---------------------------------------------------------------------------
4590
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004591 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07004592
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004593 This is the driver exit point (invoked when module is unloaded using rmmod
4594 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07004595
4596 \param - None
4597
4598 \return - None
4599
4600 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004601static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004602{
4603 hdd_context_t *pHddCtx = NULL;
4604 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004605
4606 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
4607
4608 //Get the global vos context
4609 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4610
4611 if(!pVosContext)
4612 {
4613 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
4614 goto done;
4615 }
4616
4617 //Get the HDD context.
4618 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
4619
4620 if(!pHddCtx)
4621 {
4622 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
4623 }
4624 else
4625 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004626 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07004627 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07004628 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
4629 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07004630 }
4631
4632 pHddCtx->isLoadUnloadInProgress = TRUE;
4633 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4634
4635 //Do all the cleanup before deregistering the driver
4636 hdd_wlan_exit(pHddCtx);
4637 }
4638
Jeff Johnson295189b2012-06-20 16:38:30 -07004639 vos_preClose( &pVosContext );
4640
4641#ifdef TIMER_MANAGER
4642 vos_timer_exit();
4643#endif
4644#ifdef MEMORY_DEBUG
4645 vos_mem_exit();
4646#endif
4647
4648done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004649#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004650 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004651#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004652 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
4653}
4654
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004655/**---------------------------------------------------------------------------
4656
4657 \brief hdd_module_exit() - Exit function
4658
4659 This is the driver exit point (invoked when module is unloaded using rmmod)
4660
4661 \param - None
4662
4663 \return - None
4664
4665 --------------------------------------------------------------------------*/
4666static void __exit hdd_module_exit(void)
4667{
4668 hdd_driver_exit();
4669}
4670
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004671#ifdef MODULE
4672static int fwpath_changed_handler(const char *kmessage,
4673 struct kernel_param *kp)
4674{
4675 /* nothing to do when driver is DLKM */
4676 return 0;
4677}
4678
4679static int con_mode_handler(const char *kmessage,
4680 struct kernel_param *kp)
4681{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07004682 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004683}
4684#else /* #ifdef MODULE */
4685/**---------------------------------------------------------------------------
4686
4687 \brief fwpath_changed_handler() - Handler Function
4688
4689 This is the driver entry point
4690 - delayed driver initialization when driver is statically linked
4691 - invoked when module parameter fwpath is modified from userpspace to signal
4692 initializing the WLAN driver
4693
4694 \return - 0 for success, non zero for failure
4695
4696 --------------------------------------------------------------------------*/
4697static int fwpath_changed_handler(const char *kmessage,
4698 struct kernel_param *kp)
4699{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004700 int ret_status;
4701
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004702 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004703 ret_status = hdd_driver_init();
4704 wlan_hdd_inited = ret_status ? 0 : 1;
4705 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004706 }
4707
4708 hdd_driver_exit();
4709
4710 msleep(200);
4711
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004712 ret_status = hdd_driver_init();
4713 wlan_hdd_inited = ret_status ? 0 : 1;
4714 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004715}
4716
Jeff Johnson295189b2012-06-20 16:38:30 -07004717/**---------------------------------------------------------------------------
4718
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004719 \brief con_mode_handler() -
4720
4721 Handler function for module param con_mode when it is changed by userspace
4722 Dynamically linked - do nothing
4723 Statically linked - exit and init driver, as in rmmod and insmod
4724
4725 \param -
4726
4727 \return -
4728
4729 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004730static int con_mode_handler(const char *kmessage,
4731 struct kernel_param *kp)
4732{
4733 int ret = param_set_int(kmessage, kp);
4734
4735 if (ret)
4736 return ret;
4737
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004738 return fwpath_changed_handler(kmessage, kp);
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004739}
4740#endif /* #ifdef MODULE */
4741
4742/**---------------------------------------------------------------------------
4743
Jeff Johnson295189b2012-06-20 16:38:30 -07004744 \brief hdd_get_conparam() -
4745
4746 This is the driver exit point (invoked when module is unloaded using rmmod)
4747
4748 \param - None
4749
4750 \return - tVOS_CON_MODE
4751
4752 --------------------------------------------------------------------------*/
4753tVOS_CON_MODE hdd_get_conparam ( void )
4754{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004755#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07004756 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004757#else
4758 return (tVOS_CON_MODE)curr_con_mode;
4759#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004760}
4761void hdd_set_conparam ( v_UINT_t newParam )
4762{
4763 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004764#ifndef MODULE
4765 curr_con_mode = con_mode;
4766#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004767}
4768/**---------------------------------------------------------------------------
4769
4770 \brief hdd_softap_sta_deauth() - function
4771
4772 This to take counter measure to handle deauth req from HDD
4773
4774 \param - pAdapter - Pointer to the HDD
4775
4776 \param - enable - boolean value
4777
4778 \return - None
4779
4780 --------------------------------------------------------------------------*/
4781
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004782VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07004783{
Jeff Johnson295189b2012-06-20 16:38:30 -07004784 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004785 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07004786
4787 ENTER();
4788
4789 hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4790
4791 //Ignore request to deauth bcmc station
4792 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004793 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004794
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004795 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07004796
4797 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004798 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004799}
4800
4801/**---------------------------------------------------------------------------
4802
4803 \brief hdd_softap_sta_disassoc() - function
4804
4805 This to take counter measure to handle deauth req from HDD
4806
4807 \param - pAdapter - Pointer to the HDD
4808
4809 \param - enable - boolean value
4810
4811 \return - None
4812
4813 --------------------------------------------------------------------------*/
4814
4815void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
4816{
4817 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4818
4819 ENTER();
4820
4821 hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4822
4823 //Ignore request to disassoc bcmc station
4824 if( pDestMacAddress[0] & 0x1 )
4825 return;
4826
4827 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
4828}
4829
4830void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
4831{
4832 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4833
4834 ENTER();
4835
4836 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4837
4838 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
4839}
4840
Jeff Johnson295189b2012-06-20 16:38:30 -07004841/**---------------------------------------------------------------------------
4842 *
4843 * \brief hdd_get__concurrency_mode() -
4844 *
4845 *
4846 * \param - None
4847 *
4848 * \return - CONCURRENCY MODE
4849 *
4850 * --------------------------------------------------------------------------*/
4851tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
4852{
4853 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
4854 hdd_context_t *pHddCtx;
4855
4856 if (NULL != pVosContext)
4857 {
4858 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
4859 if (NULL != pHddCtx)
4860 {
4861 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
4862 }
4863 }
4864
4865 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004866 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004867 return VOS_STA;
4868}
4869
4870/* Decide whether to allow/not the apps power collapse.
4871 * Allow apps power collapse if we are in connected state.
4872 * if not, allow only if we are in IMPS */
4873v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
4874{
4875 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08004876 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08004877 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07004878 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4879 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4880 hdd_adapter_t *pAdapter = NULL;
4881 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08004882 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004883
Jeff Johnson295189b2012-06-20 16:38:30 -07004884 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4885 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004886
Yathish9f22e662012-12-10 14:21:35 -08004887 concurrent_state = hdd_get_concurrency_mode();
4888
4889#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4890 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
4891 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
4892 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
4893 return TRUE;
4894#endif
4895
Jeff Johnson295189b2012-06-20 16:38:30 -07004896 /*loop through all adapters. TBD fix for Concurrency */
4897 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4898 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4899 {
4900 pAdapter = pAdapterNode->pAdapter;
4901 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4902 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4903 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08004904 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07004905 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08004906 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08004907 (eANI_BOOLEAN_TRUE == scanRspPending) ||
4908 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07004909 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08004910 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08004911 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
4912 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07004913 return FALSE;
4914 }
4915 }
4916 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4917 pAdapterNode = pNext;
4918 }
4919 return TRUE;
4920}
4921
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08004922/* Decides whether to send suspend notification to Riva
4923 * if any adapter is in BMPS; then it is required */
4924v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
4925{
4926 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
4927 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4928
4929 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
4930 {
4931 return TRUE;
4932 }
4933 return FALSE;
4934}
4935
Jeff Johnson295189b2012-06-20 16:38:30 -07004936void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
4937{
4938 switch(mode)
4939 {
4940 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07004941 case WLAN_HDD_P2P_CLIENT:
4942 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004943 case WLAN_HDD_SOFTAP:
Jeff Johnsone7245742012-09-05 17:12:55 -07004944 pHddCtx->concurrency_mode |= (1 << mode);
4945 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07004946 break;
4947 default:
4948 break;
4949
4950 }
4951 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
4952 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
4953}
4954
4955
4956void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
4957{
4958 switch(mode)
4959 {
4960 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07004961 case WLAN_HDD_P2P_CLIENT:
4962 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004963 case WLAN_HDD_SOFTAP:
4964 pHddCtx->no_of_sessions[mode]--;
4965 if (!(pHddCtx->no_of_sessions[mode]))
4966 pHddCtx->concurrency_mode &= (~(1 << mode));
4967 break;
4968 default:
4969 break;
4970 }
4971 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
4972 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
4973}
4974
Jeff Johnsone7245742012-09-05 17:12:55 -07004975/**---------------------------------------------------------------------------
4976 *
4977 * \brief wlan_hdd_restart_init
4978 *
4979 * This function initalizes restart timer/flag. An internal function.
4980 *
4981 * \param - pHddCtx
4982 *
4983 * \return - None
4984 *
4985 * --------------------------------------------------------------------------*/
4986
4987static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
4988{
4989 /* Initialize */
4990 pHddCtx->hdd_restart_retries = 0;
4991 atomic_set(&pHddCtx->isRestartInProgress, 0);
4992 vos_timer_init(&pHddCtx->hdd_restart_timer,
4993 VOS_TIMER_TYPE_SW,
4994 wlan_hdd_restart_timer_cb,
4995 pHddCtx);
4996}
4997/**---------------------------------------------------------------------------
4998 *
4999 * \brief wlan_hdd_restart_deinit
5000 *
5001 * This function cleans up the resources used. An internal function.
5002 *
5003 * \param - pHddCtx
5004 *
5005 * \return - None
5006 *
5007 * --------------------------------------------------------------------------*/
5008
5009static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
5010{
5011
5012 VOS_STATUS vos_status;
5013 /* Block any further calls */
5014 atomic_set(&pHddCtx->isRestartInProgress, 1);
5015 /* Cleanup */
5016 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
5017 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005018 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005019 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
5020 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005021 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005022
5023}
5024
5025/**---------------------------------------------------------------------------
5026 *
5027 * \brief wlan_hdd_framework_restart
5028 *
5029 * This function uses a cfg80211 API to start a framework initiated WLAN
5030 * driver module unload/load.
5031 *
5032 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
5033 *
5034 *
5035 * \param - pHddCtx
5036 *
5037 * \return - VOS_STATUS_SUCCESS: Success
5038 * VOS_STATUS_E_EMPTY: Adapter is Empty
5039 * VOS_STATUS_E_NOMEM: No memory
5040
5041 * --------------------------------------------------------------------------*/
5042
5043static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
5044{
5045 VOS_STATUS status = VOS_STATUS_SUCCESS;
5046 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5047 int len = (sizeof (struct ieee80211_mgmt));
5048 struct ieee80211_mgmt *mgmt = NULL;
5049
5050 /* Prepare the DEAUTH managment frame with reason code */
5051 mgmt = kzalloc(len, GFP_KERNEL);
5052 if(mgmt == NULL)
5053 {
5054 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1250df42012-12-10 14:31:52 -08005055 "%s: memory allocation failed (%d bytes)", __func__, len);
Jeff Johnsone7245742012-09-05 17:12:55 -07005056 return VOS_STATUS_E_NOMEM;
5057 }
5058 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
5059
5060 /* Iterate over all adapters/devices */
5061 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5062 do
5063 {
5064 if( (status == VOS_STATUS_SUCCESS) &&
5065 pAdapterNode &&
5066 pAdapterNode->pAdapter)
5067 {
5068 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5069 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
5070 pAdapterNode->pAdapter->dev->name,
5071 pAdapterNode->pAdapter->device_mode,
5072 pHddCtx->hdd_restart_retries + 1);
5073 /*
5074 * CFG80211 event to restart the driver
5075 *
5076 * 'cfg80211_send_unprot_deauth' sends a
5077 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
5078 * of SME(Linux Kernel) state machine.
5079 *
5080 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
5081 * the driver.
5082 *
5083 */
5084
5085 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
5086 }
5087 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5088 pAdapterNode = pNext;
5089 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
5090
5091
5092 /* Free the allocated management frame */
5093 kfree(mgmt);
5094
5095 /* Retry until we unload or reach max count */
5096 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
5097 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
5098
5099 return status;
5100
5101}
5102/**---------------------------------------------------------------------------
5103 *
5104 * \brief wlan_hdd_restart_timer_cb
5105 *
5106 * Restart timer callback. An internal function.
5107 *
5108 * \param - User data:
5109 *
5110 * \return - None
5111 *
5112 * --------------------------------------------------------------------------*/
5113
5114void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
5115{
5116 hdd_context_t *pHddCtx = usrDataForCallback;
5117 wlan_hdd_framework_restart(pHddCtx);
5118 return;
5119
5120}
5121
5122
5123/**---------------------------------------------------------------------------
5124 *
5125 * \brief wlan_hdd_restart_driver
5126 *
5127 * This function sends an event to supplicant to restart the WLAN driver.
5128 *
5129 * This function is called from vos_wlanRestart.
5130 *
5131 * \param - pHddCtx
5132 *
5133 * \return - VOS_STATUS_SUCCESS: Success
5134 * VOS_STATUS_E_EMPTY: Adapter is Empty
5135 * VOS_STATUS_E_ALREADY: Request already in progress
5136
5137 * --------------------------------------------------------------------------*/
5138VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
5139{
5140 VOS_STATUS status = VOS_STATUS_SUCCESS;
5141
5142 /* A tight check to make sure reentrancy */
5143 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
5144 {
5145 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
5146 "%s: WLAN restart is already in progress", __func__);
5147
5148 return VOS_STATUS_E_ALREADY;
5149 }
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005150 /* when WLAN driver is statically linked, then invoke SSR by sending
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005151 * the reset interrupt. If it is DLKM, then use restart API
5152 */
5153#ifdef MODULE
Jeff Johnsone7245742012-09-05 17:12:55 -07005154 status = wlan_hdd_framework_restart(pHddCtx);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005155#else
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005156#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005157 wcnss_reset_intr();
5158#endif
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005159#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005160
Jeff Johnsone7245742012-09-05 17:12:55 -07005161 return status;
5162}
5163
5164
Jeff Johnson295189b2012-06-20 16:38:30 -07005165//Register the module init/exit functions
5166module_init(hdd_module_init);
5167module_exit(hdd_module_exit);
5168
5169MODULE_LICENSE("Dual BSD/GPL");
5170MODULE_AUTHOR("Qualcomm Atheros, Inc.");
5171MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
5172
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005173module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
5174 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07005175
5176module_param_call(fwpath, fwpath_changed_handler, param_get_string, fwpath,
5177 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);