blob: ef5a03f20b53b80f2fe47142a51cc09433bf3a84 [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 Nakkalab977a972013-02-18 19:15:09 -08001719 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08001720#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001721 init_completion(&pHddCtx->mc_sus_event_var);
1722 init_completion(&pHddCtx->tx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07001723 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07001724
Jeff Johnson295189b2012-06-20 16:38:30 -07001725 pAdapter->isLinkUpSvcNeeded = FALSE;
1726 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
1727 //Init the net_device structure
1728 strlcpy(pWlanDev->name, name, IFNAMSIZ);
1729
1730 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
1731 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
1732 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
1733 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
1734
1735 hdd_set_station_ops( pAdapter->dev );
1736
1737 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07001738 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
1739 pAdapter->wdev.wiphy = pHddCtx->wiphy;
1740 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07001741 /* set pWlanDev's parent to underlying device */
1742 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
1743 }
1744
1745 return pAdapter;
1746}
1747
1748VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
1749{
1750 struct net_device *pWlanDev = pAdapter->dev;
1751 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1752 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1753 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1754
1755 if( rtnl_lock_held )
1756 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001757 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07001758 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
1759 {
1760 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
1761 return VOS_STATUS_E_FAILURE;
1762 }
1763 }
1764 if (register_netdevice(pWlanDev))
1765 {
1766 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
1767 return VOS_STATUS_E_FAILURE;
1768 }
1769 }
1770 else
1771 {
1772 if(register_netdev(pWlanDev))
1773 {
1774 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
1775 return VOS_STATUS_E_FAILURE;
1776 }
1777 }
1778 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
1779
1780 return VOS_STATUS_SUCCESS;
1781}
1782
1783eHalStatus hdd_smeCloseSessionCallback(void *pContext)
1784{
1785 if(pContext != NULL)
1786 {
1787 clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags);
1788
1789 /* need to make sure all of our scheduled work has completed.
1790 * This callback is called from MC thread context, so it is safe to
1791 * to call below flush workqueue API from here.
1792 */
1793 flush_scheduled_work();
1794 complete(&((hdd_adapter_t*)pContext)->session_close_comp_var);
1795 }
1796 return eHAL_STATUS_SUCCESS;
1797}
1798
1799VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
1800{
1801 struct net_device *pWlanDev = pAdapter->dev;
1802 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1803 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1804 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1805 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1806 int rc = 0;
1807
1808 INIT_COMPLETION(pAdapter->session_open_comp_var);
1809 //Open a SME session for future operation
1810 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
1811 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
1812 if ( !HAL_STATUS_SUCCESS( halStatus ) )
1813 {
1814 hddLog(VOS_TRACE_LEVEL_FATAL,
1815 "sme_OpenSession() failed with status code %08d [x%08lx]",
1816 halStatus, halStatus );
1817 status = VOS_STATUS_E_FAILURE;
1818 goto error_sme_open;
1819 }
1820
1821 //Block on a completion variable. Can't wait forever though.
1822 rc = wait_for_completion_interruptible_timeout(
1823 &pAdapter->session_open_comp_var,
1824 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1825 if (!rc)
1826 {
1827 hddLog(VOS_TRACE_LEVEL_FATAL,
1828 "Session is not opened within timeout period code %08d", rc );
1829 status = VOS_STATUS_E_FAILURE;
1830 goto error_sme_open;
1831 }
1832
1833 // Register wireless extensions
1834 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
1835 {
1836 hddLog(VOS_TRACE_LEVEL_FATAL,
1837 "hdd_register_wext() failed with status code %08d [x%08lx]",
1838 halStatus, halStatus );
1839 status = VOS_STATUS_E_FAILURE;
1840 goto error_register_wext;
1841 }
1842 //Safe to register the hard_start_xmit function again
1843#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1844 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
1845#else
1846 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
1847#endif
1848
1849 //Set the Connection State to Not Connected
1850 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
1851
1852 //Set the default operation channel
1853 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
1854
1855 /* Make the default Auth Type as OPEN*/
1856 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
1857
1858 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
1859 {
1860 hddLog(VOS_TRACE_LEVEL_FATAL,
1861 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
1862 status, status );
1863 goto error_init_txrx;
1864 }
1865
1866 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1867
1868 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
1869 {
1870 hddLog(VOS_TRACE_LEVEL_FATAL,
1871 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
1872 status, status );
1873 goto error_wmm_init;
1874 }
1875
1876 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1877
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001878#ifdef FEATURE_WLAN_TDLS
1879 if(0 != wlan_hdd_tdls_init(pAdapter))
1880 {
1881 status = VOS_STATUS_E_FAILURE;
1882 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
1883 goto error_tdls_init;
1884 }
1885 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
1886#endif
1887
Jeff Johnson295189b2012-06-20 16:38:30 -07001888 return VOS_STATUS_SUCCESS;
1889
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001890#ifdef FEATURE_WLAN_TDLS
1891error_tdls_init:
1892 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1893 hdd_wmm_adapter_close(pAdapter);
1894#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001895error_wmm_init:
1896 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1897 hdd_deinit_tx_rx(pAdapter);
1898error_init_txrx:
1899 hdd_UnregisterWext(pWlanDev);
1900error_register_wext:
1901 if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
1902 {
1903 INIT_COMPLETION(pAdapter->session_close_comp_var);
1904 if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
1905 pAdapter->sessionId,
1906 hdd_smeCloseSessionCallback, pAdapter ) )
1907 {
1908 //Block on a completion variable. Can't wait forever though.
1909 wait_for_completion_interruptible_timeout(
1910 &pAdapter->session_close_comp_var,
1911 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1912 }
1913}
1914error_sme_open:
1915 return status;
1916}
1917
Jeff Johnson295189b2012-06-20 16:38:30 -07001918void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1919{
1920 hdd_cfg80211_state_t *cfgState;
1921
1922 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1923
1924 if( NULL != cfgState->buf )
1925 {
1926 int rc;
1927 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
1928 rc = wait_for_completion_interruptible_timeout(
1929 &pAdapter->tx_action_cnf_event,
1930 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
1931 if(!rc)
1932 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08001933 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001934 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
1935 }
1936 }
1937 return;
1938}
Jeff Johnson295189b2012-06-20 16:38:30 -07001939
1940void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1941{
1942 ENTER();
1943 switch ( pAdapter->device_mode )
1944 {
1945 case WLAN_HDD_INFRA_STATION:
1946 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07001947 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07001948 {
1949 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1950 {
1951 hdd_deinit_tx_rx( pAdapter );
1952 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1953 }
1954
1955 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
1956 {
1957 hdd_wmm_adapter_close( pAdapter );
1958 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1959 }
1960
Jeff Johnson295189b2012-06-20 16:38:30 -07001961 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08001962#ifdef FEATURE_WLAN_TDLS
1963 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
1964 {
1965 wlan_hdd_tdls_exit(pAdapter);
1966 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
1967 }
1968#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001969
1970 break;
1971 }
1972
1973 case WLAN_HDD_SOFTAP:
1974 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07001975 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001976 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001977
1978 hdd_unregister_hostapd(pAdapter);
1979 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07001980 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07001981 break;
1982 }
1983
1984 case WLAN_HDD_MONITOR:
1985 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001986 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07001987 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1988 {
1989 hdd_deinit_tx_rx( pAdapter );
1990 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1991 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001992 if(NULL != pAdapterforTx)
1993 {
1994 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
1995 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001996 break;
1997 }
1998
1999
2000 default:
2001 break;
2002 }
2003
2004 EXIT();
2005}
2006
2007void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
2008{
2009 struct net_device *pWlanDev = pAdapter->dev;
2010
2011 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
2012 if( rtnl_held )
2013 {
2014 unregister_netdevice(pWlanDev);
2015 }
2016 else
2017 {
2018 unregister_netdev(pWlanDev);
2019 }
2020 // note that the pAdapter is no longer valid at this point
2021 // since the memory has been reclaimed
2022 }
2023
2024}
2025
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08002026void hdd_set_pwrparams(hdd_context_t *pHddCtx)
2027{
2028 tSirSetPowerParamsReq powerRequest = { 0 };
2029
2030 powerRequest.uIgnoreDTIM = 1;
2031
2032 if (pHddCtx->cfg_ini->enableModulatedDTIM)
2033 {
2034 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
2035 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2036 }
2037 else
2038 {
2039 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
2040 }
2041
2042 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
2043 *specified during Enter/Exit BMPS when LCD off*/
2044 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2045 NULL, eANI_BOOLEAN_FALSE);
2046 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2047 NULL, eANI_BOOLEAN_FALSE);
2048
2049 /* switch to the DTIM specified in cfg.ini */
2050 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2051 "Switch to DTIM%d", powerRequest.uListenInterval);
2052 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2053
2054}
2055
2056void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
2057{
2058 /*Switch back to DTIM 1*/
2059 tSirSetPowerParamsReq powerRequest = { 0 };
2060
2061 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
2062 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2063
2064 /* Update ignoreDTIM and ListedInterval in CFG with default values */
2065 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2066 NULL, eANI_BOOLEAN_FALSE);
2067 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2068 NULL, eANI_BOOLEAN_FALSE);
2069
2070 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2071 "Switch to DTIM%d",powerRequest.uListenInterval);
2072 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2073
2074}
2075
Jeff Johnson295189b2012-06-20 16:38:30 -07002076VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
2077{
2078 VOS_STATUS status = VOS_STATUS_SUCCESS;
2079
2080 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2081 {
2082 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2083 }
2084
2085 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2086 {
2087 sme_StartAutoBmpsTimer(pHddCtx->hHal);
2088 }
2089
2090 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2091 {
2092 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2093 }
2094
2095 return status;
2096}
2097
2098VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
2099{
2100 hdd_adapter_t *pAdapter = NULL;
2101 eHalStatus halStatus;
2102 VOS_STATUS status = VOS_STATUS_E_INVAL;
2103 v_BOOL_t disableBmps = FALSE;
2104 v_BOOL_t disableImps = FALSE;
2105
2106 switch(session_type)
2107 {
2108 case WLAN_HDD_INFRA_STATION:
2109 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002110 case WLAN_HDD_P2P_CLIENT:
2111 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002112 //Exit BMPS -> Is Sta/P2P Client is already connected
2113 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
2114 if((NULL != pAdapter)&&
2115 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2116 {
2117 disableBmps = TRUE;
2118 }
2119
2120 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
2121 if((NULL != pAdapter)&&
2122 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2123 {
2124 disableBmps = TRUE;
2125 }
2126
2127 //Exit both Bmps and Imps incase of Go/SAP Mode
2128 if((WLAN_HDD_SOFTAP == session_type) ||
2129 (WLAN_HDD_P2P_GO == session_type))
2130 {
2131 disableBmps = TRUE;
2132 disableImps = TRUE;
2133 }
2134
2135 if(TRUE == disableImps)
2136 {
2137 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2138 {
2139 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2140 }
2141 }
2142
2143 if(TRUE == disableBmps)
2144 {
2145 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2146 {
2147 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2148
2149 if(eHAL_STATUS_SUCCESS != halStatus)
2150 {
2151 status = VOS_STATUS_E_FAILURE;
2152 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
2153 VOS_ASSERT(0);
2154 return status;
2155 }
2156 }
2157
2158 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2159 {
2160 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
2161
2162 if(eHAL_STATUS_SUCCESS != halStatus)
2163 {
2164 status = VOS_STATUS_E_FAILURE;
2165 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
2166 VOS_ASSERT(0);
2167 return status;
2168 }
2169 }
2170 }
2171
2172 if((TRUE == disableBmps) ||
2173 (TRUE == disableImps))
2174 {
2175 /* Now, get the chip into Full Power now */
2176 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
2177 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
2178 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
2179
2180 if(halStatus != eHAL_STATUS_SUCCESS)
2181 {
2182 if(halStatus == eHAL_STATUS_PMC_PENDING)
2183 {
2184 //Block on a completion variable. Can't wait forever though
2185 wait_for_completion_interruptible_timeout(
2186 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
2187 }
2188 else
2189 {
2190 status = VOS_STATUS_E_FAILURE;
2191 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
2192 VOS_ASSERT(0);
2193 return status;
2194 }
2195 }
2196
2197 status = VOS_STATUS_SUCCESS;
2198 }
2199
2200 break;
2201 }
2202 return status;
2203}
2204
2205hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002206 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07002207 tANI_U8 rtnl_held )
2208{
2209 hdd_adapter_t *pAdapter = NULL;
2210 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
2211 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2212 VOS_STATUS exitbmpsStatus;
2213
2214 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
2215
2216 //Disable BMPS incase of Concurrency
2217 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
2218
2219 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
2220 {
2221 //Fail to Exit BMPS
2222 VOS_ASSERT(0);
2223 return NULL;
2224 }
2225
2226 switch(session_type)
2227 {
2228 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002229 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002230 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002231 {
2232 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2233
2234 if( NULL == pAdapter )
2235 return NULL;
2236
Jeff Johnsone7245742012-09-05 17:12:55 -07002237 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
2238 NL80211_IFTYPE_P2P_CLIENT:
2239 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07002240
Jeff Johnson295189b2012-06-20 16:38:30 -07002241 pAdapter->device_mode = session_type;
2242
2243 status = hdd_init_station_mode( pAdapter );
2244 if( VOS_STATUS_SUCCESS != status )
2245 goto err_free_netdev;
2246
2247 status = hdd_register_interface( pAdapter, rtnl_held );
2248 if( VOS_STATUS_SUCCESS != status )
2249 {
2250 hdd_deinit_adapter(pHddCtx, pAdapter);
2251 goto err_free_netdev;
2252 }
2253 //Stop the Interface TX queue.
2254 netif_tx_disable(pAdapter->dev);
2255 //netif_tx_disable(pWlanDev);
2256 netif_carrier_off(pAdapter->dev);
2257
2258 break;
2259 }
2260
Jeff Johnson295189b2012-06-20 16:38:30 -07002261 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002262 case WLAN_HDD_SOFTAP:
2263 {
2264 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
2265 if( NULL == pAdapter )
2266 return NULL;
2267
Jeff Johnson295189b2012-06-20 16:38:30 -07002268 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
2269 NL80211_IFTYPE_AP:
2270 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002271 pAdapter->device_mode = session_type;
2272
2273 status = hdd_init_ap_mode(pAdapter);
2274 if( VOS_STATUS_SUCCESS != status )
2275 goto err_free_netdev;
2276
2277 status = hdd_register_hostapd( pAdapter, rtnl_held );
2278 if( VOS_STATUS_SUCCESS != status )
2279 {
2280 hdd_deinit_adapter(pHddCtx, pAdapter);
2281 goto err_free_netdev;
2282 }
2283
2284 netif_tx_disable(pAdapter->dev);
2285 netif_carrier_off(pAdapter->dev);
2286
2287 hdd_set_conparam( 1 );
2288 break;
2289 }
2290 case WLAN_HDD_MONITOR:
2291 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002292 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2293 if( NULL == pAdapter )
2294 return NULL;
2295
2296 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
2297 pAdapter->device_mode = session_type;
2298 status = hdd_register_interface( pAdapter, rtnl_held );
2299#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
2300 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
2301#else
2302 pAdapter->dev->open = hdd_mon_open;
2303 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
2304#endif
2305 hdd_init_tx_rx( pAdapter );
2306 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2307 //Set adapter to be used for data tx. It will use either GO or softap.
2308 pAdapter->sessionCtx.monitor.pAdapterForTx =
2309 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07002310 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
2311 {
2312 pAdapter->sessionCtx.monitor.pAdapterForTx =
2313 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
2314 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002315 /* This workqueue will be used to transmit management packet over
2316 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07002317 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
2318 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
2319 return NULL;
2320 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07002321
Jeff Johnson295189b2012-06-20 16:38:30 -07002322 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
2323 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07002324 }
2325 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002326 case WLAN_HDD_FTM:
2327 {
2328 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2329
2330 if( NULL == pAdapter )
2331 return NULL;
2332 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
2333 * message while loading driver in FTM mode. */
2334 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
2335 pAdapter->device_mode = session_type;
2336 status = hdd_register_interface( pAdapter, rtnl_held );
2337 }
2338 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002339 default:
2340 {
2341 VOS_ASSERT(0);
2342 return NULL;
2343 }
2344 }
2345
2346
2347 if( VOS_STATUS_SUCCESS == status )
2348 {
2349 //Add it to the hdd's session list.
2350 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
2351 if( NULL == pHddAdapterNode )
2352 {
2353 status = VOS_STATUS_E_NOMEM;
2354 }
2355 else
2356 {
2357 pHddAdapterNode->pAdapter = pAdapter;
2358 status = hdd_add_adapter_back ( pHddCtx,
2359 pHddAdapterNode );
2360 }
2361 }
2362
2363 if( VOS_STATUS_SUCCESS != status )
2364 {
2365 if( NULL != pAdapter )
2366 {
2367 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
2368 pAdapter = NULL;
2369 }
2370 if( NULL != pHddAdapterNode )
2371 {
2372 vos_mem_free( pHddAdapterNode );
2373 }
2374
2375 goto resume_bmps;
2376 }
2377
2378 if(VOS_STATUS_SUCCESS == status)
2379 {
2380 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
2381
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07002382 //Initialize the WoWL service
2383 if(!hdd_init_wowl(pAdapter))
2384 {
2385 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
2386 goto err_free_netdev;
2387 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002388 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002389 return pAdapter;
2390
2391err_free_netdev:
2392 free_netdev(pAdapter->dev);
2393 wlan_hdd_release_intf_addr( pHddCtx,
2394 pAdapter->macAddressCurrent.bytes );
2395
2396resume_bmps:
2397 //If bmps disabled enable it
2398 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
2399 {
2400 hdd_enable_bmps_imps(pHddCtx);
2401 }
2402 return NULL;
2403}
2404
2405VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
2406 tANI_U8 rtnl_held )
2407{
2408 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
2409 VOS_STATUS status;
2410
2411 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
2412 if( VOS_STATUS_SUCCESS != status )
2413 return status;
2414
2415 while ( pCurrent->pAdapter != pAdapter )
2416 {
2417 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
2418 if( VOS_STATUS_SUCCESS != status )
2419 break;
2420
2421 pCurrent = pNext;
2422 }
2423 pAdapterNode = pCurrent;
2424 if( VOS_STATUS_SUCCESS == status )
2425 {
2426 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2427 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
2428 hdd_remove_adapter( pHddCtx, pAdapterNode );
2429 vos_mem_free( pAdapterNode );
2430
Jeff Johnson295189b2012-06-20 16:38:30 -07002431
2432 /* If there is a single session of STA/P2P client, re-enable BMPS */
2433 if ((!vos_concurrent_sessions_running()) &&
2434 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
2435 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
2436 {
2437 hdd_enable_bmps_imps(pHddCtx);
2438 }
2439
2440 return VOS_STATUS_SUCCESS;
2441 }
2442
2443 return VOS_STATUS_E_FAILURE;
2444}
2445
2446VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
2447{
2448 hdd_adapter_list_node_t *pHddAdapterNode;
2449 VOS_STATUS status;
2450
2451 ENTER();
2452
2453 do
2454 {
2455 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
2456 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
2457 {
2458 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
2459 vos_mem_free( pHddAdapterNode );
2460 }
2461 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
2462
2463 EXIT();
2464
2465 return VOS_STATUS_SUCCESS;
2466}
2467
2468void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
2469{
2470 v_U8_t addIE[1] = {0};
2471
2472 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2473 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
2474 eANI_BOOLEAN_FALSE) )
2475 {
2476 hddLog(LOGE,
2477 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
2478 }
2479
2480 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2481 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
2482 eANI_BOOLEAN_FALSE) )
2483 {
2484 hddLog(LOGE,
2485 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
2486 }
2487
2488 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2489 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
2490 eANI_BOOLEAN_FALSE) )
2491 {
2492 hddLog(LOGE,
2493 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
2494 }
2495}
2496
2497VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2498{
2499 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2500 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2501 union iwreq_data wrqu;
2502
2503 ENTER();
2504
2505 switch(pAdapter->device_mode)
2506 {
2507 case WLAN_HDD_INFRA_STATION:
2508 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002509 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002510 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
2511 {
2512 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
2513 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
2514 pAdapter->sessionId,
2515 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
2516 else
2517 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
2518 pAdapter->sessionId,
2519 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2520 //success implies disconnect command got queued up successfully
2521 if(halStatus == eHAL_STATUS_SUCCESS)
2522 {
2523 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
2524 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2525 }
2526 memset(&wrqu, '\0', sizeof(wrqu));
2527 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2528 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2529 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2530 }
2531 else
2532 {
2533 hdd_abort_mac_scan(pHddCtx);
2534 }
2535
2536 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
2537 {
2538 INIT_COMPLETION(pAdapter->session_close_comp_var);
2539 if (eHAL_STATUS_SUCCESS ==
2540 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
2541 hdd_smeCloseSessionCallback, pAdapter))
2542 {
2543 //Block on a completion variable. Can't wait forever though.
2544 wait_for_completion_interruptible_timeout(
2545 &pAdapter->session_close_comp_var,
2546 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2547 }
2548 }
2549
2550 break;
2551
2552 case WLAN_HDD_SOFTAP:
2553 case WLAN_HDD_P2P_GO:
2554 //Any softap specific cleanup here...
2555 mutex_lock(&pHddCtx->sap_lock);
2556 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2557 {
2558 VOS_STATUS status;
2559 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2560
2561 //Stop Bss.
2562 status = WLANSAP_StopBss(pHddCtx->pvosContext);
2563 if (VOS_IS_STATUS_SUCCESS(status))
2564 {
2565 hdd_hostapd_state_t *pHostapdState =
2566 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2567
2568 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2569
2570 if (!VOS_IS_STATUS_SUCCESS(status))
2571 {
2572 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002573 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002574 }
2575 }
2576 else
2577 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002578 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002579 }
2580 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2581
2582 if (eHAL_STATUS_FAILURE ==
2583 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
2584 0, NULL, eANI_BOOLEAN_FALSE))
2585 {
2586 hddLog(LOGE,
2587 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002588 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002589 }
2590
2591 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2592 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2593 eANI_BOOLEAN_FALSE) )
2594 {
2595 hddLog(LOGE,
2596 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
2597 }
2598
2599 // Reset WNI_CFG_PROBE_RSP Flags
2600 wlan_hdd_reset_prob_rspies(pAdapter);
2601 kfree(pAdapter->sessionCtx.ap.beacon);
2602 pAdapter->sessionCtx.ap.beacon = NULL;
2603 }
2604 mutex_unlock(&pHddCtx->sap_lock);
2605 break;
2606 case WLAN_HDD_MONITOR:
2607 break;
2608 default:
2609 break;
2610 }
2611
2612 EXIT();
2613 return VOS_STATUS_SUCCESS;
2614}
2615
2616VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
2617{
2618 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2619 VOS_STATUS status;
2620 hdd_adapter_t *pAdapter;
2621
2622 ENTER();
2623
2624 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2625
2626 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2627 {
2628 pAdapter = pAdapterNode->pAdapter;
2629 netif_tx_disable(pAdapter->dev);
2630 netif_carrier_off(pAdapter->dev);
2631
2632 hdd_stop_adapter( pHddCtx, pAdapter );
2633
2634 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2635 pAdapterNode = pNext;
2636 }
2637
2638 EXIT();
2639
2640 return VOS_STATUS_SUCCESS;
2641}
2642
2643VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
2644{
2645 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2646 VOS_STATUS status;
2647 hdd_adapter_t *pAdapter;
2648
2649 ENTER();
2650
2651 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2652
2653 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2654 {
2655 pAdapter = pAdapterNode->pAdapter;
2656 netif_tx_disable(pAdapter->dev);
2657 netif_carrier_off(pAdapter->dev);
2658
2659 //Record whether STA is associated
2660 pAdapter->sessionCtx.station.bSendDisconnect =
2661 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
2662 VOS_TRUE : VOS_FALSE;
2663
2664 hdd_deinit_tx_rx(pAdapter);
2665 hdd_wmm_adapter_close(pAdapter);
2666
2667 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2668 pAdapterNode = pNext;
2669 }
2670
2671 EXIT();
2672
2673 return VOS_STATUS_SUCCESS;
2674}
2675
2676VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
2677{
2678 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2679 VOS_STATUS status;
2680 hdd_adapter_t *pAdapter;
2681 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
2682
2683 ENTER();
2684
2685 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2686
2687 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2688 {
2689 pAdapter = pAdapterNode->pAdapter;
2690
2691 switch(pAdapter->device_mode)
2692 {
2693 case WLAN_HDD_INFRA_STATION:
2694 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002695 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002696 hdd_init_station_mode(pAdapter);
2697 /* Open the gates for HDD to receive Wext commands */
2698 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002699 pHddCtx->scan_info.mScanPending = FALSE;
2700 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002701
2702 //Trigger the initial scan
2703 hdd_wlan_initial_scan(pAdapter);
2704
2705 //Indicate disconnect event to supplicant if associated previously
2706 if(pAdapter->sessionCtx.station.bSendDisconnect)
2707 {
2708 union iwreq_data wrqu;
2709 memset(&wrqu, '\0', sizeof(wrqu));
2710 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2711 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2712 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2713 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
2714
Jeff Johnson295189b2012-06-20 16:38:30 -07002715 /* indicate disconnected event to nl80211 */
2716 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
2717 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002718 }
2719 break;
2720
2721 case WLAN_HDD_SOFTAP:
2722 /* softAP can handle SSR */
2723 break;
2724
2725 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002726 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
2727 __func__);
2728 /* event supplicant to restart */
2729 cfg80211_del_sta(pAdapter->dev,
2730 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002731 break;
2732
2733 case WLAN_HDD_MONITOR:
2734 /* monitor interface start */
2735 break;
2736 default:
2737 break;
2738 }
2739
2740 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2741 pAdapterNode = pNext;
2742 }
2743
2744 EXIT();
2745
2746 return VOS_STATUS_SUCCESS;
2747}
2748
2749VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
2750{
2751 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2752 hdd_adapter_t *pAdapter;
2753 VOS_STATUS status;
2754 v_U32_t roamId;
2755
2756 ENTER();
2757
2758 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2759
2760 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2761 {
2762 pAdapter = pAdapterNode->pAdapter;
2763
2764 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
2765 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
2766 {
2767 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2768 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2769
2770 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2771 init_completion(&pAdapter->disconnect_comp_var);
2772 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
2773 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2774
2775 wait_for_completion_interruptible_timeout(
2776 &pAdapter->disconnect_comp_var,
2777 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2778
2779 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
2780 pHddCtx->isAmpAllowed = VOS_FALSE;
2781 sme_RoamConnect(pHddCtx->hHal,
2782 pAdapter->sessionId, &(pWextState->roamProfile),
2783 &roamId);
2784 }
2785
2786 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2787 pAdapterNode = pNext;
2788 }
2789
2790 EXIT();
2791
2792 return VOS_STATUS_SUCCESS;
2793}
2794
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07002795void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
2796{
2797 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2798 VOS_STATUS status;
2799 hdd_adapter_t *pAdapter;
2800 hdd_station_ctx_t *pHddStaCtx;
2801 hdd_ap_ctx_t *pHddApCtx;
2802 hdd_hostapd_state_t * pHostapdState;
2803 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
2804 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
2805 const char *p2pMode = "DEV";
2806 const char *ccMode = "Standalone";
2807 int n;
2808
2809 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2810 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2811 {
2812 pAdapter = pAdapterNode->pAdapter;
2813 switch (pAdapter->device_mode) {
2814 case WLAN_HDD_INFRA_STATION:
2815 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2816 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
2817 staChannel = pHddStaCtx->conn_info.operationChannel;
2818 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
2819 }
2820 break;
2821 case WLAN_HDD_P2P_CLIENT:
2822 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2823 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
2824 p2pChannel = pHddStaCtx->conn_info.operationChannel;
2825 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
2826 p2pMode = "CLI";
2827 }
2828 break;
2829 case WLAN_HDD_P2P_GO:
2830 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2831 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2832 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
2833 p2pChannel = pHddApCtx->operatingChannel;
2834 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
2835 }
2836 p2pMode = "GO";
2837 break;
2838 case WLAN_HDD_SOFTAP:
2839 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
2840 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2841 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
2842 apChannel = pHddApCtx->operatingChannel;
2843 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
2844 }
2845 break;
2846 default:
2847 break;
2848 }
2849 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2850 pAdapterNode = pNext;
2851 }
2852 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
2853 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
2854 }
2855 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
2856 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
2857 if (p2pChannel > 0) {
2858 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
2859 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
2860 }
2861 if (apChannel > 0) {
2862 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
2863 apChannel, MAC_ADDR_ARRAY(apBssid));
2864 }
2865
2866 if (p2pChannel > 0 && apChannel > 0) {
2867 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
2868 }
2869}
2870
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002871bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07002872{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002873 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07002874}
2875
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002876/* Once SSR is disabled then it cannot be set. */
2877void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07002878{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002879 if (HDD_SSR_DISABLED == isSsrRequired)
2880 return;
2881
Jeff Johnson295189b2012-06-20 16:38:30 -07002882 isSsrRequired = value;
2883}
2884
2885VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
2886 hdd_adapter_list_node_t** ppAdapterNode)
2887{
2888 VOS_STATUS status;
2889 spin_lock(&pHddCtx->hddAdapters.lock);
2890 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
2891 (hdd_list_node_t**) ppAdapterNode );
2892 spin_unlock(&pHddCtx->hddAdapters.lock);
2893 return status;
2894}
2895
2896VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
2897 hdd_adapter_list_node_t* pAdapterNode,
2898 hdd_adapter_list_node_t** pNextAdapterNode)
2899{
2900 VOS_STATUS status;
2901 spin_lock(&pHddCtx->hddAdapters.lock);
2902 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
2903 (hdd_list_node_t*) pAdapterNode,
2904 (hdd_list_node_t**)pNextAdapterNode );
2905
2906 spin_unlock(&pHddCtx->hddAdapters.lock);
2907 return status;
2908}
2909
2910VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
2911 hdd_adapter_list_node_t* pAdapterNode)
2912{
2913 VOS_STATUS status;
2914 spin_lock(&pHddCtx->hddAdapters.lock);
2915 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
2916 &pAdapterNode->node );
2917 spin_unlock(&pHddCtx->hddAdapters.lock);
2918 return status;
2919}
2920
2921VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
2922 hdd_adapter_list_node_t** ppAdapterNode)
2923{
2924 VOS_STATUS status;
2925 spin_lock(&pHddCtx->hddAdapters.lock);
2926 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
2927 (hdd_list_node_t**) ppAdapterNode );
2928 spin_unlock(&pHddCtx->hddAdapters.lock);
2929 return status;
2930}
2931
2932VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
2933 hdd_adapter_list_node_t* pAdapterNode)
2934{
2935 VOS_STATUS status;
2936 spin_lock(&pHddCtx->hddAdapters.lock);
2937 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
2938 (hdd_list_node_t*) pAdapterNode );
2939 spin_unlock(&pHddCtx->hddAdapters.lock);
2940 return status;
2941}
2942
2943VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
2944 hdd_adapter_list_node_t* pAdapterNode)
2945{
2946 VOS_STATUS status;
2947 spin_lock(&pHddCtx->hddAdapters.lock);
2948 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
2949 (hdd_list_node_t*) pAdapterNode );
2950 spin_unlock(&pHddCtx->hddAdapters.lock);
2951 return status;
2952}
2953
2954hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
2955 tSirMacAddr macAddr )
2956{
2957 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2958 hdd_adapter_t *pAdapter;
2959 VOS_STATUS status;
2960
2961 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2962
2963 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2964 {
2965 pAdapter = pAdapterNode->pAdapter;
2966
2967 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
2968 macAddr, sizeof(tSirMacAddr) ) )
2969 {
2970 return pAdapter;
2971 }
2972 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2973 pAdapterNode = pNext;
2974 }
2975
2976 return NULL;
2977
2978}
2979
2980hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
2981{
2982 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2983 hdd_adapter_t *pAdapter;
2984 VOS_STATUS status;
2985
2986 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2987
2988 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2989 {
2990 pAdapter = pAdapterNode->pAdapter;
2991
2992 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
2993 IFNAMSIZ ) )
2994 {
2995 return pAdapter;
2996 }
2997 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2998 pAdapterNode = pNext;
2999 }
3000
3001 return NULL;
3002
3003}
3004
3005hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
3006{
3007 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3008 hdd_adapter_t *pAdapter;
3009 VOS_STATUS status;
3010
3011 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3012
3013 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3014 {
3015 pAdapter = pAdapterNode->pAdapter;
3016
3017 if( pAdapter && (mode == pAdapter->device_mode) )
3018 {
3019 return pAdapter;
3020 }
3021 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3022 pAdapterNode = pNext;
3023 }
3024
3025 return NULL;
3026
3027}
3028
3029//Remove this function later
3030hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
3031{
3032 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3033 hdd_adapter_t *pAdapter;
3034 VOS_STATUS status;
3035
3036 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3037
3038 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3039 {
3040 pAdapter = pAdapterNode->pAdapter;
3041
3042 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
3043 {
3044 return pAdapter;
3045 }
3046
3047 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3048 pAdapterNode = pNext;
3049 }
3050
3051 return NULL;
3052
3053}
3054
Jeff Johnson295189b2012-06-20 16:38:30 -07003055/**---------------------------------------------------------------------------
3056
3057 \brief hdd_set_monitor_tx_adapter() -
3058
3059 This API initializes the adapter to be used while transmitting on monitor
3060 adapter.
3061
3062 \param - pHddCtx - Pointer to the HDD context.
3063 pAdapter - Adapter that will used for TX. This can be NULL.
3064 \return - None.
3065 --------------------------------------------------------------------------*/
3066void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3067{
3068 hdd_adapter_t *pMonAdapter;
3069
3070 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
3071
3072 if( NULL != pMonAdapter )
3073 {
3074 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
3075 }
3076}
Jeff Johnson295189b2012-06-20 16:38:30 -07003077/**---------------------------------------------------------------------------
3078
3079 \brief hdd_select_queue() -
3080
3081 This API returns the operating channel of the requested device mode
3082
3083 \param - pHddCtx - Pointer to the HDD context.
3084 - mode - Device mode for which operating channel is required
3085 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
3086 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
3087 \return - channel number. "0" id the requested device is not found OR it is not connected.
3088 --------------------------------------------------------------------------*/
3089v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
3090{
3091 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3092 VOS_STATUS status;
3093 hdd_adapter_t *pAdapter;
3094 v_U8_t operatingChannel = 0;
3095
3096 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3097
3098 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3099 {
3100 pAdapter = pAdapterNode->pAdapter;
3101
3102 if( mode == pAdapter->device_mode )
3103 {
3104 switch(pAdapter->device_mode)
3105 {
3106 case WLAN_HDD_INFRA_STATION:
3107 case WLAN_HDD_P2P_CLIENT:
3108 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3109 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
3110 break;
3111 case WLAN_HDD_SOFTAP:
3112 case WLAN_HDD_P2P_GO:
3113 /*softap connection info */
3114 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3115 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
3116 break;
3117 default:
3118 break;
3119 }
3120
3121 break; //Found the device of interest. break the loop
3122 }
3123
3124 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3125 pAdapterNode = pNext;
3126 }
3127 return operatingChannel;
3128}
3129
3130#ifdef WLAN_FEATURE_PACKET_FILTERING
3131/**---------------------------------------------------------------------------
3132
3133 \brief hdd_set_multicast_list() -
3134
3135 This used to set the multicast address list.
3136
3137 \param - dev - Pointer to the WLAN device.
3138 - skb - Pointer to OS packet (sk_buff).
3139 \return - success/fail
3140
3141 --------------------------------------------------------------------------*/
3142static void hdd_set_multicast_list(struct net_device *dev)
3143{
3144 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07003145 int mc_count;
3146 int i = 0;
3147 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303148
3149 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07003150 {
3151 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303152 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003153 return;
3154 }
3155
3156 if (dev->flags & IFF_ALLMULTI)
3157 {
3158 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003159 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303160 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003161 }
3162 else
3163 {
3164 mc_count = netdev_mc_count(dev);
3165 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003166 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07003167 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
3168 {
3169 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003170 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303171 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003172 return;
3173 }
3174
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303175 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07003176
3177 netdev_for_each_mc_addr(ha, dev) {
3178 if (i == mc_count)
3179 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303180 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
3181 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
3182 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003183 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303184 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07003185 i++;
3186 }
3187 }
3188 return;
3189}
3190#endif
3191
3192/**---------------------------------------------------------------------------
3193
3194 \brief hdd_select_queue() -
3195
3196 This function is registered with the Linux OS for network
3197 core to decide which queue to use first.
3198
3199 \param - dev - Pointer to the WLAN device.
3200 - skb - Pointer to OS packet (sk_buff).
3201 \return - ac, Queue Index/access category corresponding to UP in IP header
3202
3203 --------------------------------------------------------------------------*/
3204v_U16_t hdd_select_queue(struct net_device *dev,
3205 struct sk_buff *skb)
3206{
3207 return hdd_wmm_select_queue(dev, skb);
3208}
3209
3210
3211/**---------------------------------------------------------------------------
3212
3213 \brief hdd_wlan_initial_scan() -
3214
3215 This function triggers the initial scan
3216
3217 \param - pAdapter - Pointer to the HDD adapter.
3218
3219 --------------------------------------------------------------------------*/
3220void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
3221{
3222 tCsrScanRequest scanReq;
3223 tCsrChannelInfo channelInfo;
3224 eHalStatus halStatus;
3225 unsigned long scanId;
3226 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3227
3228 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
3229 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
3230 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
3231
3232 if(sme_Is11dSupported(pHddCtx->hHal))
3233 {
3234 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
3235 if ( HAL_STATUS_SUCCESS( halStatus ) )
3236 {
3237 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
3238 if( !scanReq.ChannelInfo.ChannelList )
3239 {
3240 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
3241 vos_mem_free(channelInfo.ChannelList);
3242 return;
3243 }
3244 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
3245 channelInfo.numOfChannels);
3246 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
3247 vos_mem_free(channelInfo.ChannelList);
3248 }
3249
3250 scanReq.scanType = eSIR_PASSIVE_SCAN;
3251 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
3252 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
3253 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
3254 }
3255 else
3256 {
3257 scanReq.scanType = eSIR_ACTIVE_SCAN;
3258 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
3259 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
3260 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
3261 }
3262
3263 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
3264 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3265 {
3266 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
3267 __func__, halStatus );
3268 }
3269
3270 if(sme_Is11dSupported(pHddCtx->hHal))
3271 vos_mem_free(scanReq.ChannelInfo.ChannelList);
3272}
3273
3274struct fullPowerContext
3275{
3276 struct completion completion;
3277 unsigned int magic;
3278};
3279#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
3280
3281/**---------------------------------------------------------------------------
3282
3283 \brief hdd_full_power_callback() - HDD full power callback function
3284
3285 This is the function invoked by SME to inform the result of a full power
3286 request issued by HDD
3287
3288 \param - callbackcontext - Pointer to cookie
3289 \param - status - result of request
3290
3291 \return - None
3292
3293 --------------------------------------------------------------------------*/
3294static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
3295{
3296 struct fullPowerContext *pContext = callbackContext;
3297
3298 hddLog(VOS_TRACE_LEVEL_INFO,
3299 "%s: context = %p, status = %d", pContext, status);
3300
3301 if (NULL == callbackContext)
3302 {
3303 hddLog(VOS_TRACE_LEVEL_ERROR,
3304 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003305 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07003306 return;
3307 }
3308
3309 /* there is a race condition that exists between this callback function
3310 and the caller since the caller could time out either before or
3311 while this code is executing. we'll assume the timeout hasn't
3312 occurred, but we'll verify that right before we save our work */
3313
3314 if (POWER_CONTEXT_MAGIC != pContext->magic)
3315 {
3316 /* the caller presumably timed out so there is nothing we can do */
3317 hddLog(VOS_TRACE_LEVEL_WARN,
3318 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003319 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07003320 return;
3321 }
3322
3323 /* the race is on. caller could have timed out immediately after
3324 we verified the magic, but if so, caller will wait a short time
3325 for us to notify the caller, so the context will stay valid */
3326 complete(&pContext->completion);
3327}
3328
3329/**---------------------------------------------------------------------------
3330
3331 \brief hdd_wlan_exit() - HDD WLAN exit function
3332
3333 This is the driver exit point (invoked during rmmod)
3334
3335 \param - pHddCtx - Pointer to the HDD Context
3336
3337 \return - None
3338
3339 --------------------------------------------------------------------------*/
3340void hdd_wlan_exit(hdd_context_t *pHddCtx)
3341{
3342 eHalStatus halStatus;
3343 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
3344 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05303345 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003346 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003347 struct fullPowerContext powerContext;
3348 long lrc;
3349
3350 ENTER();
3351
Jeff Johnson88ba7742013-02-27 14:36:02 -08003352 if (VOS_FTM_MODE != hdd_get_conparam())
3353 {
3354 // Unloading, restart logic is no more required.
3355 wlan_hdd_restart_deinit(pHddCtx);
3356 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003357
Jeff Johnson295189b2012-06-20 16:38:30 -07003358 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003359 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003360 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003361 {
3362 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
3363 WLAN_HDD_INFRA_STATION);
3364 if (pAdapter == NULL)
3365 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3366
3367 if (pAdapter != NULL)
3368 {
3369 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
3370 hdd_UnregisterWext(pAdapter->dev);
3371 }
3372 }
3373 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003374
Jeff Johnson295189b2012-06-20 16:38:30 -07003375 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08003376 {
3377 wlan_hdd_ftm_close(pHddCtx);
3378 goto free_hdd_ctx;
3379 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003380 //Stop the Interface TX queue.
3381 //netif_tx_disable(pWlanDev);
3382 //netif_carrier_off(pWlanDev);
3383
Jeff Johnson295189b2012-06-20 16:38:30 -07003384 if (VOS_STA_SAP_MODE == hdd_get_conparam())
3385 {
3386 pAdapter = hdd_get_adapter(pHddCtx,
3387 WLAN_HDD_SOFTAP);
3388 }
3389 else
3390 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003391 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003392 {
3393 pAdapter = hdd_get_adapter(pHddCtx,
3394 WLAN_HDD_INFRA_STATION);
3395 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003396 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003397 /* DeRegister with platform driver as client for Suspend/Resume */
3398 vosStatus = hddDeregisterPmOps(pHddCtx);
3399 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3400 {
3401 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
3402 VOS_ASSERT(0);
3403 }
3404
3405 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
3406 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3407 {
3408 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
3409 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003410
3411 // Cancel any outstanding scan requests. We are about to close all
3412 // of our adapters, but an adapter structure is what SME passes back
3413 // to our callback function. Hence if there are any outstanding scan
3414 // requests then there is a race condition between when the adapter
3415 // is closed and when the callback is invoked. We try to resolve that
3416 // race condition here by canceling any outstanding scans before we
3417 // close the adapters.
3418 // Note that the scans may be cancelled in an asynchronous manner, so
3419 // ideally there needs to be some kind of synchronization. Rather than
3420 // introduce a new synchronization here, we will utilize the fact that
3421 // we are about to Request Full Power, and since that is synchronized,
3422 // the expectation is that by the time Request Full Power has completed,
3423 // all scans will be cancelled.
3424 hdd_abort_mac_scan( pHddCtx );
3425
3426 //Disable IMPS/BMPS as we do not want the device to enter any power
3427 //save mode during shutdown
3428 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3429 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3430 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
3431
3432 //Ensure that device is in full power as we will touch H/W during vos_Stop
3433 init_completion(&powerContext.completion);
3434 powerContext.magic = POWER_CONTEXT_MAGIC;
3435
3436 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
3437 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
3438
3439 if (eHAL_STATUS_SUCCESS != halStatus)
3440 {
3441 if (eHAL_STATUS_PMC_PENDING == halStatus)
3442 {
3443 /* request was sent -- wait for the response */
3444 lrc = wait_for_completion_interruptible_timeout(
3445 &powerContext.completion,
3446 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
3447 /* either we have a response or we timed out
3448 either way, first invalidate our magic */
3449 powerContext.magic = 0;
3450 if (lrc <= 0)
3451 {
3452 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003453 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07003454 /* there is a race condition such that the callback
3455 function could be executing at the same time we are. of
3456 primary concern is if the callback function had already
3457 verified the "magic" but hasn't yet set the completion
3458 variable. Since the completion variable is on our
3459 stack, we'll delay just a bit to make sure the data is
3460 still valid if that is the case */
3461 msleep(50);
3462 }
3463 }
3464 else
3465 {
3466 hddLog(VOS_TRACE_LEVEL_ERROR,
3467 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003468 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07003469 VOS_ASSERT(0);
3470 /* continue -- need to clean up as much as possible */
3471 }
3472 }
3473
3474 // Unregister the Net Device Notifier
3475 unregister_netdevice_notifier(&hdd_netdev_notifier);
3476
Jeff Johnson295189b2012-06-20 16:38:30 -07003477 hdd_stop_all_adapters( pHddCtx );
3478
Jeff Johnson295189b2012-06-20 16:38:30 -07003479#ifdef WLAN_BTAMP_FEATURE
3480 vosStatus = WLANBAP_Stop(pVosContext);
3481 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3482 {
3483 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3484 "%s: Failed to stop BAP",__func__);
3485 }
3486#endif //WLAN_BTAMP_FEATURE
3487
3488 //Stop all the modules
3489 vosStatus = vos_stop( pVosContext );
3490 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3491 {
3492 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3493 "%s: Failed to stop VOSS",__func__);
3494 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3495 }
3496
Jeff Johnson295189b2012-06-20 16:38:30 -07003497 //Assert Deep sleep signal now to put Libra HW in lowest power state
3498 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
3499 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3500
3501 //Vote off any PMIC voltage supplies
3502 vos_chipPowerDown(NULL, NULL, NULL);
3503
3504 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
3505
3506 //Clean up HDD Nlink Service
3507 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
3508 nl_srv_exit();
3509
3510 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07003511 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003512
3513 //Close the scheduler before calling vos_close to make sure no thread is
3514 // scheduled after the each module close is called i.e after all the data
3515 // structures are freed.
3516 vosStatus = vos_sched_close( pVosContext );
3517 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
3518 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
3519 "%s: Failed to close VOSS Scheduler",__func__);
3520 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3521 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003522#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07003523#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3524 /* Destroy the wake lock */
3525 wake_lock_destroy(&pHddCtx->rx_wake_lock);
3526#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08003527 /* Destroy the wake lock */
3528 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003529#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003530
3531 //Close VOSS
3532 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
3533 vos_close(pVosContext);
3534
Jeff Johnson295189b2012-06-20 16:38:30 -07003535 //Close Watchdog
3536 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3537 vos_watchdog_close(pVosContext);
3538
3539 /* Cancel the vote for XO Core ON.
3540 * This is done here to ensure there is no race condition since MC, TX and WD threads have
3541 * exited at this point
3542 */
3543 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
3544 " when WLAN is turned OFF\n");
3545 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
3546 {
3547 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
3548 " Not returning failure."
3549 " Power consumed will be high\n");
3550 }
3551
3552 hdd_close_all_adapters( pHddCtx );
3553
3554
3555 //Free up dynamically allocated members inside HDD Adapter
3556 kfree(pHddCtx->cfg_ini);
3557 pHddCtx->cfg_ini= NULL;
3558
3559 /* free the power on lock from platform driver */
3560 if (free_riva_power_on_lock("wlan"))
3561 {
3562 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
3563 __func__);
3564 }
3565
Jeff Johnson88ba7742013-02-27 14:36:02 -08003566free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08003567 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07003568 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07003569 if (hdd_is_ssr_required())
3570 {
3571 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07003572 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07003573 msleep(5000);
3574 }
3575 hdd_set_ssr_required (VOS_FALSE);
3576}
3577
3578
3579/**---------------------------------------------------------------------------
3580
3581 \brief hdd_update_config_from_nv() - Function to update the contents of
3582 the running configuration with parameters taken from NV storage
3583
3584 \param - pHddCtx - Pointer to the HDD global context
3585
3586 \return - VOS_STATUS_SUCCESS if successful
3587
3588 --------------------------------------------------------------------------*/
3589static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
3590{
Jeff Johnson295189b2012-06-20 16:38:30 -07003591 v_BOOL_t itemIsValid = VOS_FALSE;
3592 VOS_STATUS status;
3593 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
3594 v_U8_t macLoop;
3595
3596 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
3597 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
3598 if(status != VOS_STATUS_SUCCESS)
3599 {
3600 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
3601 return VOS_STATUS_E_FAILURE;
3602 }
3603
3604 if (itemIsValid == VOS_TRUE)
3605 {
3606 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
3607 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
3608 VOS_MAX_CONCURRENCY_PERSONA);
3609 if(status != VOS_STATUS_SUCCESS)
3610 {
3611 /* Get MAC from NV fail, not update CFG info
3612 * INI MAC value will be used for MAC setting */
3613 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
3614 return VOS_STATUS_E_FAILURE;
3615 }
3616
3617 /* If first MAC is not valid, treat all others are not valid
3618 * Then all MACs will be got from ini file */
3619 if(vos_is_macaddr_zero(&macFromNV[0]))
3620 {
3621 /* MAC address in NV file is not configured yet */
3622 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
3623 return VOS_STATUS_E_INVAL;
3624 }
3625
3626 /* Get MAC address from NV, update CFG info */
3627 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
3628 {
3629 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
3630 {
3631 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
3632 /* This MAC is not valid, skip it
3633 * This MAC will be got from ini file */
3634 }
3635 else
3636 {
3637 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
3638 (v_U8_t *)&macFromNV[macLoop].bytes[0],
3639 VOS_MAC_ADDR_SIZE);
3640 }
3641 }
3642 }
3643 else
3644 {
3645 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
3646 return VOS_STATUS_E_FAILURE;
3647 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003648
Jeff Johnson295189b2012-06-20 16:38:30 -07003649
3650 return VOS_STATUS_SUCCESS;
3651}
3652
3653/**---------------------------------------------------------------------------
3654
3655 \brief hdd_post_voss_start_config() - HDD post voss start config helper
3656
3657 \param - pAdapter - Pointer to the HDD
3658
3659 \return - None
3660
3661 --------------------------------------------------------------------------*/
3662VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
3663{
3664 eHalStatus halStatus;
3665 v_U32_t listenInterval;
3666
Jeff Johnson295189b2012-06-20 16:38:30 -07003667
3668 // Send ready indication to the HDD. This will kick off the MAC
3669 // into a 'running' state and should kick off an initial scan.
3670 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
3671 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3672 {
3673 hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
3674 "code %08d [x%08x]",__func__, halStatus, halStatus );
3675 return VOS_STATUS_E_FAILURE;
3676 }
3677
3678 // Set default LI into HDD context,
3679 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
3680 // And RIVA will crash
3681 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
3682 pHddCtx->hdd_actual_LI_value = listenInterval;
3683
3684 return VOS_STATUS_SUCCESS;
3685}
3686
Jeff Johnson295189b2012-06-20 16:38:30 -07003687/* wake lock APIs for HDD */
3688void hdd_prevent_suspend(void)
3689{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003690#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003691 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003692#else
3693 wcnss_prevent_suspend();
3694#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003695}
3696
3697void hdd_allow_suspend(void)
3698{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003699#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003700 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003701#else
3702 wcnss_allow_suspend();
3703#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003704}
3705
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003706void hdd_allow_suspend_timeout(v_U32_t timeout)
3707{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003708#ifdef WLAN_OPEN_SOURCE
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003709 wake_lock_timeout(&wlan_wake_lock, timeout);
3710#else
3711 /* Do nothing as there is no API in wcnss for timeout*/
3712#endif
3713}
3714
Jeff Johnson295189b2012-06-20 16:38:30 -07003715/**---------------------------------------------------------------------------
3716
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003717 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
3718 information between Host and Riva
3719
3720 This function gets reported version of FW
3721 It also finds the version of Riva headers used to compile the host
3722 It compares the above two and prints a warning if they are different
3723 It gets the SW and HW version string
3724 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
3725 indicating the features they support through a bitmap
3726
3727 \param - pHddCtx - Pointer to HDD context
3728
3729 \return - void
3730
3731 --------------------------------------------------------------------------*/
3732
3733void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
3734{
3735
3736 tSirVersionType versionCompiled;
3737 tSirVersionType versionReported;
3738 tSirVersionString versionString;
3739 tANI_U8 fwFeatCapsMsgSupported = 0;
3740 VOS_STATUS vstatus;
3741
3742 /* retrieve and display WCNSS version information */
3743 do {
3744
3745 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
3746 &versionCompiled);
3747 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3748 {
3749 hddLog(VOS_TRACE_LEVEL_FATAL,
3750 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003751 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003752 break;
3753 }
3754
3755 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
3756 &versionReported);
3757 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3758 {
3759 hddLog(VOS_TRACE_LEVEL_FATAL,
3760 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003761 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003762 break;
3763 }
3764
3765 if ((versionCompiled.major != versionReported.major) ||
3766 (versionCompiled.minor != versionReported.minor) ||
3767 (versionCompiled.version != versionReported.version) ||
3768 (versionCompiled.revision != versionReported.revision))
3769 {
3770 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
3771 "Host expected %u.%u.%u.%u\n",
3772 WLAN_MODULE_NAME,
3773 (int)versionReported.major,
3774 (int)versionReported.minor,
3775 (int)versionReported.version,
3776 (int)versionReported.revision,
3777 (int)versionCompiled.major,
3778 (int)versionCompiled.minor,
3779 (int)versionCompiled.version,
3780 (int)versionCompiled.revision);
3781 }
3782 else
3783 {
3784 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
3785 WLAN_MODULE_NAME,
3786 (int)versionReported.major,
3787 (int)versionReported.minor,
3788 (int)versionReported.version,
3789 (int)versionReported.revision);
3790 }
3791
3792 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
3793 versionString,
3794 sizeof(versionString));
3795 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3796 {
3797 hddLog(VOS_TRACE_LEVEL_FATAL,
3798 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003799 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003800 break;
3801 }
3802
3803 pr_info("%s: WCNSS software version %s\n",
3804 WLAN_MODULE_NAME, versionString);
3805
3806 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
3807 versionString,
3808 sizeof(versionString));
3809 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3810 {
3811 hddLog(VOS_TRACE_LEVEL_FATAL,
3812 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003813 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003814 break;
3815 }
3816
3817 pr_info("%s: WCNSS hardware version %s\n",
3818 WLAN_MODULE_NAME, versionString);
3819
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003820 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
3821 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003822 send the message only if it the riva is 1.1
3823 minor numbers for different riva branches:
3824 0 -> (1.0)Mainline Build
3825 1 -> (1.1)Mainline Build
3826 2->(1.04) Stability Build
3827 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003828 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003829 ((versionReported.minor>=1) && (versionReported.version>=1)))
3830 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
3831 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003832
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003833 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08003834 {
3835#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
3836 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
3837 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
3838#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003839 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08003840 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003841
3842 } while (0);
3843
3844}
3845
3846/**---------------------------------------------------------------------------
3847
Jeff Johnson295189b2012-06-20 16:38:30 -07003848 \brief hdd_wlan_startup() - HDD init function
3849
3850 This is the driver startup code executed once a WLAN device has been detected
3851
3852 \param - dev - Pointer to the underlying device
3853
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003854 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07003855
3856 --------------------------------------------------------------------------*/
3857
3858int hdd_wlan_startup(struct device *dev )
3859{
3860 VOS_STATUS status;
3861 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003862 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003863 hdd_context_t *pHddCtx = NULL;
3864 v_CONTEXT_t pVosContext= NULL;
3865#ifdef WLAN_BTAMP_FEATURE
3866 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
3867 WLANBAP_ConfigType btAmpConfig;
3868 hdd_config_t *pConfig;
3869#endif
3870 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07003871 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003872
3873 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07003874 /*
3875 * cfg80211: wiphy allocation
3876 */
3877 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
3878
3879 if(wiphy == NULL)
3880 {
3881 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003882 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003883 }
3884
3885 pHddCtx = wiphy_priv(wiphy);
3886
Jeff Johnson295189b2012-06-20 16:38:30 -07003887 //Initialize the adapter context to zeros.
3888 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
3889
Jeff Johnson295189b2012-06-20 16:38:30 -07003890 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003891 hdd_prevent_suspend();
3892 pHddCtx->isLoadUnloadInProgress = TRUE;
3893
3894 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
3895
3896 /*Get vos context here bcoz vos_open requires it*/
3897 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
3898
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08003899 if(pVosContext == NULL)
3900 {
3901 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
3902 goto err_free_hdd_context;
3903 }
3904
Jeff Johnson295189b2012-06-20 16:38:30 -07003905 //Save the Global VOSS context in adapter context for future.
3906 pHddCtx->pvosContext = pVosContext;
3907
3908 //Save the adapter context in global context for future.
3909 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
3910
Jeff Johnson295189b2012-06-20 16:38:30 -07003911 pHddCtx->parent_dev = dev;
3912
3913 init_completion(&pHddCtx->full_pwr_comp_var);
3914 init_completion(&pHddCtx->standby_comp_var);
3915 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003916 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003917 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003918
3919 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
3920
3921 // Load all config first as TL config is needed during vos_open
3922 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
3923 if(pHddCtx->cfg_ini == NULL)
3924 {
3925 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
3926 goto err_free_hdd_context;
3927 }
3928
3929 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
3930
3931 // Read and parse the qcom_cfg.ini file
3932 status = hdd_parse_config_ini( pHddCtx );
3933 if ( VOS_STATUS_SUCCESS != status )
3934 {
3935 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
3936 __func__, WLAN_INI_FILE);
3937 goto err_config;
3938 }
3939
Jeff Johnson295189b2012-06-20 16:38:30 -07003940 /*
3941 * cfg80211: Initialization and registration ...
3942 */
3943 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
3944 {
3945 hddLog(VOS_TRACE_LEVEL_FATAL,
3946 "%s: wlan_hdd_cfg80211_register return failure", __func__);
3947 goto err_wiphy_reg;
3948 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003949
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003950 // Update VOS trace levels based upon the cfg.ini
3951 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
3952 pHddCtx->cfg_ini->vosTraceEnableBAP);
3953 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
3954 pHddCtx->cfg_ini->vosTraceEnableTL);
3955 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
3956 pHddCtx->cfg_ini->vosTraceEnableWDI);
3957 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
3958 pHddCtx->cfg_ini->vosTraceEnableHDD);
3959 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
3960 pHddCtx->cfg_ini->vosTraceEnableSME);
3961 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
3962 pHddCtx->cfg_ini->vosTraceEnablePE);
3963 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
3964 pHddCtx->cfg_ini->vosTraceEnableWDA);
3965 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
3966 pHddCtx->cfg_ini->vosTraceEnableSYS);
3967 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
3968 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003969 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
3970 pHddCtx->cfg_ini->vosTraceEnableSAP);
3971 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
3972 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003973
Jeff Johnson295189b2012-06-20 16:38:30 -07003974 // Update WDI trace levels based upon the cfg.ini
3975 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
3976 pHddCtx->cfg_ini->wdiTraceEnableDAL);
3977 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
3978 pHddCtx->cfg_ini->wdiTraceEnableCTL);
3979 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
3980 pHddCtx->cfg_ini->wdiTraceEnableDAT);
3981 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
3982 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003983
Jeff Johnson88ba7742013-02-27 14:36:02 -08003984 if (VOS_FTM_MODE == hdd_get_conparam())
3985 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003986 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
3987 {
3988 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
3989 goto err_free_hdd_context;
3990 }
3991 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
3992 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08003993 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003994
Jeff Johnson88ba7742013-02-27 14:36:02 -08003995 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07003996 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3997 {
3998 status = vos_watchdog_open(pVosContext,
3999 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
4000
4001 if(!VOS_IS_STATUS_SUCCESS( status ))
4002 {
4003 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004004 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07004005 }
4006 }
4007
4008 pHddCtx->isLogpInProgress = FALSE;
4009 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4010
Jeff Johnson295189b2012-06-20 16:38:30 -07004011 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
4012 if(!VOS_IS_STATUS_SUCCESS(status))
4013 {
4014 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004015 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004016 }
4017
Jeff Johnson295189b2012-06-20 16:38:30 -07004018 status = vos_open( &pVosContext, 0);
4019 if ( !VOS_IS_STATUS_SUCCESS( status ))
4020 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004021 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
4022 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07004023 }
4024
Jeff Johnson295189b2012-06-20 16:38:30 -07004025 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
4026
4027 if ( NULL == pHddCtx->hHal )
4028 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004029 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004030 goto err_vosclose;
4031 }
4032
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004033 status = vos_preStart( pHddCtx->pvosContext );
4034 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4035 {
4036 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
4037 goto err_vosclose;
4038 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004039
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004040 /* Note that the vos_preStart() sequence triggers the cfg download.
4041 The cfg download must occur before we update the SME config
4042 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07004043 status = hdd_set_sme_config( pHddCtx );
4044
4045 if ( VOS_STATUS_SUCCESS != status )
4046 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004047 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
4048 goto err_vosclose;
4049 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004050
4051 //Initialize the WMM module
4052 status = hdd_wmm_init(pHddCtx);
4053 if (!VOS_IS_STATUS_SUCCESS(status))
4054 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004055 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004056 goto err_vosclose;
4057 }
4058
Jeff Johnson295189b2012-06-20 16:38:30 -07004059 /* In the integrated architecture we update the configuration from
4060 the INI file and from NV before vOSS has been started so that
4061 the final contents are available to send down to the cCPU */
4062
4063 // Apply the cfg.ini to cfg.dat
4064 if (FALSE == hdd_update_config_dat(pHddCtx))
4065 {
4066 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
4067 goto err_vosclose;
4068 }
4069
4070 // Apply the NV to cfg.dat
4071 /* Prima Update MAC address only at here */
4072 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
4073 {
4074#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
4075 /* There was not a valid set of MAC Addresses in NV. See if the
4076 default addresses were modified by the cfg.ini settings. If so,
4077 we'll use them, but if not, we'll autogenerate a set of MAC
4078 addresses based upon the device serial number */
4079
4080 static const v_MACADDR_t default_address =
4081 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
4082 unsigned int serialno;
4083 int i;
4084
4085 serialno = wcnss_get_serial_number();
4086 if ((0 != serialno) &&
4087 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
4088 sizeof(default_address))))
4089 {
4090 /* cfg.ini has the default address, invoke autogen logic */
4091
4092 /* MAC address has 3 bytes of OUI so we have a maximum of 3
4093 bytes of the serial number that can be used to generate
4094 the other 3 bytes of the MAC address. Mask off all but
4095 the lower 3 bytes (this will also make sure we don't
4096 overflow in the next step) */
4097 serialno &= 0x00FFFFFF;
4098
4099 /* we need a unique address for each session */
4100 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
4101
4102 /* autogen all addresses */
4103 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4104 {
4105 /* start with the entire default address */
4106 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
4107 /* then replace the lower 3 bytes */
4108 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
4109 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
4110 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
4111
4112 serialno++;
4113 }
4114
4115 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
4116 MAC_ADDRESS_STR,
4117 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4118 }
4119 else
4120#endif //WLAN_AUTOGEN_MACADDR_FEATURE
4121 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004122 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004123 "%s: Invalid MAC address in NV, using MAC from ini file "
4124 MAC_ADDRESS_STR, __func__,
4125 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4126 }
4127 }
4128 {
4129 eHalStatus halStatus;
4130 // Set the MAC Address
4131 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
4132 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
4133 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
4134 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
4135
4136 if (!HAL_STATUS_SUCCESS( halStatus ))
4137 {
4138 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
4139 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08004140 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004141 }
4142 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004143
4144 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
4145 Note: Firmware image will be read and downloaded inside vos_start API */
4146 status = vos_start( pHddCtx->pvosContext );
4147 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4148 {
4149 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
4150 goto err_vosclose;
4151 }
4152
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004153 /* Exchange capability info between Host and FW and also get versioning info from FW */
4154 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004155
4156 status = hdd_post_voss_start_config( pHddCtx );
4157 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4158 {
4159 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
4160 __func__);
4161 goto err_vosstop;
4162 }
4163
Jeff Johnson295189b2012-06-20 16:38:30 -07004164 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4165 {
4166 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
4167 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4168 }
4169 else
4170 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004171 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
4172 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4173 if (pAdapter != NULL)
4174 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304175 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07004176 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304177 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
4178 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
4179 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07004180
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304181 /* Generate the P2P Device Address. This consists of the device's
4182 * primary MAC address with the locally administered bit set.
4183 */
4184 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07004185 }
4186 else
4187 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304188 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
4189 if (p2p_dev_addr != NULL)
4190 {
4191 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
4192 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
4193 }
4194 else
4195 {
4196 hddLog(VOS_TRACE_LEVEL_FATAL,
4197 "%s: Failed to allocate mac_address for p2p_device",
4198 __func__);
4199 goto err_close_adapter;
4200 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004201 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004202
4203 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
4204 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
4205 if ( NULL == pP2pAdapter )
4206 {
4207 hddLog(VOS_TRACE_LEVEL_FATAL,
4208 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004209 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004210 goto err_close_adapter;
4211 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004212 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004213 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004214
4215 if( pAdapter == NULL )
4216 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004217 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
4218 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004219 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004220
Jeff Johnson295189b2012-06-20 16:38:30 -07004221#ifdef WLAN_BTAMP_FEATURE
4222 vStatus = WLANBAP_Open(pVosContext);
4223 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4224 {
4225 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4226 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004227 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004228 }
4229
4230 vStatus = BSL_Init(pVosContext);
4231 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4232 {
4233 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4234 "%s: Failed to Init BSL",__func__);
4235 goto err_bap_close;
4236 }
4237 vStatus = WLANBAP_Start(pVosContext);
4238 if (!VOS_IS_STATUS_SUCCESS(vStatus))
4239 {
4240 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4241 "%s: Failed to start TL",__func__);
4242 goto err_bap_close;
4243 }
4244
4245 pConfig = pHddCtx->cfg_ini;
4246 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
4247 status = WLANBAP_SetConfig(&btAmpConfig);
4248
4249#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07004250
Jeff Johnson295189b2012-06-20 16:38:30 -07004251#ifdef FEATURE_WLAN_SCAN_PNO
4252 /*SME must send channel update configuration to RIVA*/
4253 sme_UpdateChannelConfig(pHddCtx->hHal);
4254#endif
4255
Jeff Johnson295189b2012-06-20 16:38:30 -07004256 /* Register with platform driver as client for Suspend/Resume */
4257 status = hddRegisterPmOps(pHddCtx);
4258 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4259 {
4260 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
4261#ifdef WLAN_BTAMP_FEATURE
4262 goto err_bap_stop;
4263#else
Jeff Johnsone7245742012-09-05 17:12:55 -07004264 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004265#endif //WLAN_BTAMP_FEATURE
4266 }
4267
4268 /* Register TM level change handler function to the platform */
4269 status = hddDevTmRegisterNotifyCallback(pHddCtx);
4270 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4271 {
4272 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
4273 goto err_unregister_pmops;
4274 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004275
4276 /* register for riva power on lock to platform driver */
4277 if (req_riva_power_on_lock("wlan"))
4278 {
4279 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
4280 __func__);
4281 goto err_unregister_pmops;
4282 }
4283
Jeff Johnson295189b2012-06-20 16:38:30 -07004284 // register net device notifier for device change notification
4285 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4286
4287 if(ret < 0)
4288 {
4289 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
4290 goto err_free_power_on_lock;
4291 }
4292
4293 //Initialize the nlink service
4294 if(nl_srv_init() != 0)
4295 {
4296 hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
4297 goto err_reg_netdev;
4298 }
4299
4300 //Initialize the BTC service
4301 if(btc_activate_service(pHddCtx) != 0)
4302 {
4303 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
4304 goto err_nl_srv;
4305 }
4306
4307#ifdef PTT_SOCK_SVC_ENABLE
4308 //Initialize the PTT service
4309 if(ptt_sock_activate_svc(pHddCtx) != 0)
4310 {
4311 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
4312 goto err_nl_srv;
4313 }
4314#endif
4315
Jeff Johnson295189b2012-06-20 16:38:30 -07004316 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004317 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004318 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07004319 /* Action frame registered in one adapter which will
4320 * applicable to all interfaces
4321 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07004322 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07004323 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004324
4325 mutex_init(&pHddCtx->sap_lock);
4326
4327 pHddCtx->isLoadUnloadInProgress = FALSE;
4328
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004329#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004330#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4331 /* Initialize the wake lcok */
4332 wake_lock_init(&pHddCtx->rx_wake_lock,
4333 WAKE_LOCK_SUSPEND,
4334 "qcom_rx_wakelock");
4335#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004336 /* Initialize the wake lcok */
4337 wake_lock_init(&pHddCtx->sap_wake_lock,
4338 WAKE_LOCK_SUSPEND,
4339 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004340#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004341
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004342 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
4343 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07004344
4345 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4346 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004347
4348 // Initialize the restart logic
4349 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05304350
Jeff Johnson295189b2012-06-20 16:38:30 -07004351 goto success;
4352
4353err_nl_srv:
4354 nl_srv_exit();
4355
4356err_reg_netdev:
4357 unregister_netdevice_notifier(&hdd_netdev_notifier);
4358
4359err_free_power_on_lock:
4360 free_riva_power_on_lock("wlan");
4361
4362err_unregister_pmops:
4363 hddDevTmUnregisterNotifyCallback(pHddCtx);
4364 hddDeregisterPmOps(pHddCtx);
4365
4366#ifdef WLAN_BTAMP_FEATURE
4367err_bap_stop:
4368 WLANBAP_Stop(pVosContext);
4369#endif
4370
4371#ifdef WLAN_BTAMP_FEATURE
4372err_bap_close:
4373 WLANBAP_Close(pVosContext);
4374#endif
4375
Jeff Johnson295189b2012-06-20 16:38:30 -07004376err_close_adapter:
4377 hdd_close_all_adapters( pHddCtx );
4378
4379err_vosstop:
4380 vos_stop(pVosContext);
4381
4382err_vosclose:
4383 status = vos_sched_close( pVosContext );
4384 if (!VOS_IS_STATUS_SUCCESS(status)) {
4385 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4386 "%s: Failed to close VOSS Scheduler", __func__);
4387 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
4388 }
4389 vos_close(pVosContext );
4390
Jeff Johnson295189b2012-06-20 16:38:30 -07004391err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004392 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004393
4394err_wdclose:
4395 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4396 vos_watchdog_close(pVosContext);
4397
Jeff Johnson295189b2012-06-20 16:38:30 -07004398err_wiphy_reg:
4399 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004400
4401err_config:
4402 kfree(pHddCtx->cfg_ini);
4403 pHddCtx->cfg_ini= NULL;
4404
4405err_free_hdd_context:
4406 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004407 wiphy_free(wiphy) ;
4408 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004409 VOS_BUG(1);
4410
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08004411 if (hdd_is_ssr_required())
4412 {
4413 /* WDI timeout had happened during load, so SSR is needed here */
4414 subsystem_restart("wcnss");
4415 msleep(5000);
4416 }
4417 hdd_set_ssr_required (VOS_FALSE);
4418
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004419 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004420
4421success:
4422 EXIT();
4423 return 0;
4424}
4425
4426/**---------------------------------------------------------------------------
4427
Jeff Johnson32d95a32012-09-10 13:15:23 -07004428 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07004429
Jeff Johnson32d95a32012-09-10 13:15:23 -07004430 This is the driver entry point - called in different timeline depending
4431 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07004432
4433 \param - None
4434
4435 \return - 0 for success, non zero for failure
4436
4437 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07004438static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004439{
4440 VOS_STATUS status;
4441 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004442 struct device *dev = NULL;
4443 int ret_status = 0;
4444
4445 ENTER();
4446
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004447#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004448 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07004449#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004450
4451 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
4452 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
4453
4454 //Power Up Libra WLAN card first if not already powered up
4455 status = vos_chipPowerUp(NULL,NULL,NULL);
4456 if (!VOS_IS_STATUS_SUCCESS(status))
4457 {
4458 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
4459 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004460 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004461 }
4462
Jeff Johnson295189b2012-06-20 16:38:30 -07004463#ifdef ANI_BUS_TYPE_PCI
4464
4465 dev = wcnss_wlan_get_device();
4466
4467#endif // ANI_BUS_TYPE_PCI
4468
4469#ifdef ANI_BUS_TYPE_PLATFORM
4470 dev = wcnss_wlan_get_device();
4471#endif // ANI_BUS_TYPE_PLATFORM
4472
4473
4474 do {
4475 if (NULL == dev) {
4476 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
4477 ret_status = -1;
4478 break;
4479 }
4480
4481#ifdef MEMORY_DEBUG
4482 vos_mem_init();
4483#endif
4484
4485#ifdef TIMER_MANAGER
4486 vos_timer_manager_init();
4487#endif
4488
4489 /* Preopen VOSS so that it is ready to start at least SAL */
4490 status = vos_preOpen(&pVosContext);
4491
4492 if (!VOS_IS_STATUS_SUCCESS(status))
4493 {
4494 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
4495 ret_status = -1;
4496 break;
4497 }
4498
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004499#ifndef MODULE
4500 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
4501 */
4502 hdd_set_conparam((v_UINT_t)con_mode);
4503#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004504
4505 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004506 if (hdd_wlan_startup(dev))
4507 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004508 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004509 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004510 vos_preClose( &pVosContext );
4511 ret_status = -1;
4512 break;
4513 }
4514
4515 /* Cancel the vote for XO Core ON
4516 * This is done here for safety purposes in case we re-initialize without turning
4517 * it OFF in any error scenario.
4518 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004519 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07004520 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004521 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07004522 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4523 {
4524 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
4525 " Power consumed will be high\n");
4526 }
4527 } while (0);
4528
4529 if (0 != ret_status)
4530 {
4531 //Assert Deep sleep signal now to put Libra HW in lowest power state
4532 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4533 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
4534
4535 //Vote off any PMIC voltage supplies
4536 vos_chipPowerDown(NULL, NULL, NULL);
4537#ifdef TIMER_MANAGER
4538 vos_timer_exit();
4539#endif
4540#ifdef MEMORY_DEBUG
4541 vos_mem_exit();
4542#endif
4543
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004544#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004545 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004546#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004547 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
4548 }
4549 else
4550 {
4551 //Send WLAN UP indication to Nlink Service
4552 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
4553
4554 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
4555
4556 }
4557
4558 EXIT();
4559
4560 return ret_status;
4561}
4562
Jeff Johnson32d95a32012-09-10 13:15:23 -07004563/**---------------------------------------------------------------------------
4564
4565 \brief hdd_module_init() - Init Function
4566
4567 This is the driver entry point (invoked when module is loaded using insmod)
4568
4569 \param - None
4570
4571 \return - 0 for success, non zero for failure
4572
4573 --------------------------------------------------------------------------*/
4574#ifdef MODULE
4575static int __init hdd_module_init ( void)
4576{
4577 return hdd_driver_init();
4578}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004579#else /* #ifdef MODULE */
4580static int __init hdd_module_init ( void)
4581{
4582 /* Driver initialization is delayed to fwpath_changed_handler */
4583 return 0;
4584}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004585#endif /* #ifdef MODULE */
4586
Jeff Johnson295189b2012-06-20 16:38:30 -07004587
4588/**---------------------------------------------------------------------------
4589
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004590 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07004591
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004592 This is the driver exit point (invoked when module is unloaded using rmmod
4593 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07004594
4595 \param - None
4596
4597 \return - None
4598
4599 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004600static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004601{
4602 hdd_context_t *pHddCtx = NULL;
4603 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004604
4605 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
4606
4607 //Get the global vos context
4608 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4609
4610 if(!pVosContext)
4611 {
4612 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
4613 goto done;
4614 }
4615
4616 //Get the HDD context.
4617 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
4618
4619 if(!pHddCtx)
4620 {
4621 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
4622 }
4623 else
4624 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004625 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07004626 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07004627 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
4628 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07004629 }
4630
4631 pHddCtx->isLoadUnloadInProgress = TRUE;
4632 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4633
4634 //Do all the cleanup before deregistering the driver
4635 hdd_wlan_exit(pHddCtx);
4636 }
4637
Jeff Johnson295189b2012-06-20 16:38:30 -07004638 vos_preClose( &pVosContext );
4639
4640#ifdef TIMER_MANAGER
4641 vos_timer_exit();
4642#endif
4643#ifdef MEMORY_DEBUG
4644 vos_mem_exit();
4645#endif
4646
4647done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004648#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004649 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004650#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004651 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
4652}
4653
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004654/**---------------------------------------------------------------------------
4655
4656 \brief hdd_module_exit() - Exit function
4657
4658 This is the driver exit point (invoked when module is unloaded using rmmod)
4659
4660 \param - None
4661
4662 \return - None
4663
4664 --------------------------------------------------------------------------*/
4665static void __exit hdd_module_exit(void)
4666{
4667 hdd_driver_exit();
4668}
4669
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004670#ifdef MODULE
4671static int fwpath_changed_handler(const char *kmessage,
4672 struct kernel_param *kp)
4673{
4674 /* nothing to do when driver is DLKM */
4675 return 0;
4676}
4677
4678static int con_mode_handler(const char *kmessage,
4679 struct kernel_param *kp)
4680{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07004681 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004682}
4683#else /* #ifdef MODULE */
4684/**---------------------------------------------------------------------------
4685
4686 \brief fwpath_changed_handler() - Handler Function
4687
4688 This is the driver entry point
4689 - delayed driver initialization when driver is statically linked
4690 - invoked when module parameter fwpath is modified from userpspace to signal
4691 initializing the WLAN driver
4692
4693 \return - 0 for success, non zero for failure
4694
4695 --------------------------------------------------------------------------*/
4696static int fwpath_changed_handler(const char *kmessage,
4697 struct kernel_param *kp)
4698{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004699 int ret_status;
4700
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004701 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004702 ret_status = hdd_driver_init();
4703 wlan_hdd_inited = ret_status ? 0 : 1;
4704 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004705 }
4706
4707 hdd_driver_exit();
4708
4709 msleep(200);
4710
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004711 ret_status = hdd_driver_init();
4712 wlan_hdd_inited = ret_status ? 0 : 1;
4713 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004714}
4715
Jeff Johnson295189b2012-06-20 16:38:30 -07004716/**---------------------------------------------------------------------------
4717
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004718 \brief con_mode_handler() -
4719
4720 Handler function for module param con_mode when it is changed by userspace
4721 Dynamically linked - do nothing
4722 Statically linked - exit and init driver, as in rmmod and insmod
4723
4724 \param -
4725
4726 \return -
4727
4728 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004729static int con_mode_handler(const char *kmessage,
4730 struct kernel_param *kp)
4731{
4732 int ret = param_set_int(kmessage, kp);
4733
4734 if (ret)
4735 return ret;
4736
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004737 return fwpath_changed_handler(kmessage, kp);
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004738}
4739#endif /* #ifdef MODULE */
4740
4741/**---------------------------------------------------------------------------
4742
Jeff Johnson295189b2012-06-20 16:38:30 -07004743 \brief hdd_get_conparam() -
4744
4745 This is the driver exit point (invoked when module is unloaded using rmmod)
4746
4747 \param - None
4748
4749 \return - tVOS_CON_MODE
4750
4751 --------------------------------------------------------------------------*/
4752tVOS_CON_MODE hdd_get_conparam ( void )
4753{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004754#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07004755 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004756#else
4757 return (tVOS_CON_MODE)curr_con_mode;
4758#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004759}
4760void hdd_set_conparam ( v_UINT_t newParam )
4761{
4762 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004763#ifndef MODULE
4764 curr_con_mode = con_mode;
4765#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004766}
4767/**---------------------------------------------------------------------------
4768
4769 \brief hdd_softap_sta_deauth() - function
4770
4771 This to take counter measure to handle deauth req from HDD
4772
4773 \param - pAdapter - Pointer to the HDD
4774
4775 \param - enable - boolean value
4776
4777 \return - None
4778
4779 --------------------------------------------------------------------------*/
4780
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004781VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07004782{
Jeff Johnson295189b2012-06-20 16:38:30 -07004783 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004784 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07004785
4786 ENTER();
4787
4788 hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4789
4790 //Ignore request to deauth bcmc station
4791 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004792 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004793
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004794 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07004795
4796 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004797 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004798}
4799
4800/**---------------------------------------------------------------------------
4801
4802 \brief hdd_softap_sta_disassoc() - function
4803
4804 This to take counter measure to handle deauth req from HDD
4805
4806 \param - pAdapter - Pointer to the HDD
4807
4808 \param - enable - boolean value
4809
4810 \return - None
4811
4812 --------------------------------------------------------------------------*/
4813
4814void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
4815{
4816 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4817
4818 ENTER();
4819
4820 hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4821
4822 //Ignore request to disassoc bcmc station
4823 if( pDestMacAddress[0] & 0x1 )
4824 return;
4825
4826 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
4827}
4828
4829void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
4830{
4831 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4832
4833 ENTER();
4834
4835 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4836
4837 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
4838}
4839
Jeff Johnson295189b2012-06-20 16:38:30 -07004840/**---------------------------------------------------------------------------
4841 *
4842 * \brief hdd_get__concurrency_mode() -
4843 *
4844 *
4845 * \param - None
4846 *
4847 * \return - CONCURRENCY MODE
4848 *
4849 * --------------------------------------------------------------------------*/
4850tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
4851{
4852 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
4853 hdd_context_t *pHddCtx;
4854
4855 if (NULL != pVosContext)
4856 {
4857 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
4858 if (NULL != pHddCtx)
4859 {
4860 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
4861 }
4862 }
4863
4864 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004865 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004866 return VOS_STA;
4867}
4868
4869/* Decide whether to allow/not the apps power collapse.
4870 * Allow apps power collapse if we are in connected state.
4871 * if not, allow only if we are in IMPS */
4872v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
4873{
4874 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08004875 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08004876 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07004877 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4878 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4879 hdd_adapter_t *pAdapter = NULL;
4880 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08004881 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004882
Jeff Johnson295189b2012-06-20 16:38:30 -07004883 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4884 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07004885
Yathish9f22e662012-12-10 14:21:35 -08004886 concurrent_state = hdd_get_concurrency_mode();
4887
4888#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4889 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
4890 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
4891 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
4892 return TRUE;
4893#endif
4894
Jeff Johnson295189b2012-06-20 16:38:30 -07004895 /*loop through all adapters. TBD fix for Concurrency */
4896 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4897 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4898 {
4899 pAdapter = pAdapterNode->pAdapter;
4900 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4901 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4902 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08004903 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07004904 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08004905 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08004906 (eANI_BOOLEAN_TRUE == scanRspPending) ||
4907 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07004908 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08004909 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08004910 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
4911 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07004912 return FALSE;
4913 }
4914 }
4915 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4916 pAdapterNode = pNext;
4917 }
4918 return TRUE;
4919}
4920
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08004921/* Decides whether to send suspend notification to Riva
4922 * if any adapter is in BMPS; then it is required */
4923v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
4924{
4925 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
4926 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4927
4928 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
4929 {
4930 return TRUE;
4931 }
4932 return FALSE;
4933}
4934
Jeff Johnson295189b2012-06-20 16:38:30 -07004935void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
4936{
4937 switch(mode)
4938 {
4939 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07004940 case WLAN_HDD_P2P_CLIENT:
4941 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004942 case WLAN_HDD_SOFTAP:
Jeff Johnsone7245742012-09-05 17:12:55 -07004943 pHddCtx->concurrency_mode |= (1 << mode);
4944 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07004945 break;
4946 default:
4947 break;
4948
4949 }
4950 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
4951 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
4952}
4953
4954
4955void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
4956{
4957 switch(mode)
4958 {
4959 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07004960 case WLAN_HDD_P2P_CLIENT:
4961 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004962 case WLAN_HDD_SOFTAP:
4963 pHddCtx->no_of_sessions[mode]--;
4964 if (!(pHddCtx->no_of_sessions[mode]))
4965 pHddCtx->concurrency_mode &= (~(1 << mode));
4966 break;
4967 default:
4968 break;
4969 }
4970 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
4971 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
4972}
4973
Jeff Johnsone7245742012-09-05 17:12:55 -07004974/**---------------------------------------------------------------------------
4975 *
4976 * \brief wlan_hdd_restart_init
4977 *
4978 * This function initalizes restart timer/flag. An internal function.
4979 *
4980 * \param - pHddCtx
4981 *
4982 * \return - None
4983 *
4984 * --------------------------------------------------------------------------*/
4985
4986static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
4987{
4988 /* Initialize */
4989 pHddCtx->hdd_restart_retries = 0;
4990 atomic_set(&pHddCtx->isRestartInProgress, 0);
4991 vos_timer_init(&pHddCtx->hdd_restart_timer,
4992 VOS_TIMER_TYPE_SW,
4993 wlan_hdd_restart_timer_cb,
4994 pHddCtx);
4995}
4996/**---------------------------------------------------------------------------
4997 *
4998 * \brief wlan_hdd_restart_deinit
4999 *
5000 * This function cleans up the resources used. An internal function.
5001 *
5002 * \param - pHddCtx
5003 *
5004 * \return - None
5005 *
5006 * --------------------------------------------------------------------------*/
5007
5008static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
5009{
5010
5011 VOS_STATUS vos_status;
5012 /* Block any further calls */
5013 atomic_set(&pHddCtx->isRestartInProgress, 1);
5014 /* Cleanup */
5015 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
5016 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005017 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005018 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
5019 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005020 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005021
5022}
5023
5024/**---------------------------------------------------------------------------
5025 *
5026 * \brief wlan_hdd_framework_restart
5027 *
5028 * This function uses a cfg80211 API to start a framework initiated WLAN
5029 * driver module unload/load.
5030 *
5031 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
5032 *
5033 *
5034 * \param - pHddCtx
5035 *
5036 * \return - VOS_STATUS_SUCCESS: Success
5037 * VOS_STATUS_E_EMPTY: Adapter is Empty
5038 * VOS_STATUS_E_NOMEM: No memory
5039
5040 * --------------------------------------------------------------------------*/
5041
5042static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
5043{
5044 VOS_STATUS status = VOS_STATUS_SUCCESS;
5045 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5046 int len = (sizeof (struct ieee80211_mgmt));
5047 struct ieee80211_mgmt *mgmt = NULL;
5048
5049 /* Prepare the DEAUTH managment frame with reason code */
5050 mgmt = kzalloc(len, GFP_KERNEL);
5051 if(mgmt == NULL)
5052 {
5053 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1250df42012-12-10 14:31:52 -08005054 "%s: memory allocation failed (%d bytes)", __func__, len);
Jeff Johnsone7245742012-09-05 17:12:55 -07005055 return VOS_STATUS_E_NOMEM;
5056 }
5057 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
5058
5059 /* Iterate over all adapters/devices */
5060 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5061 do
5062 {
5063 if( (status == VOS_STATUS_SUCCESS) &&
5064 pAdapterNode &&
5065 pAdapterNode->pAdapter)
5066 {
5067 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5068 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
5069 pAdapterNode->pAdapter->dev->name,
5070 pAdapterNode->pAdapter->device_mode,
5071 pHddCtx->hdd_restart_retries + 1);
5072 /*
5073 * CFG80211 event to restart the driver
5074 *
5075 * 'cfg80211_send_unprot_deauth' sends a
5076 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
5077 * of SME(Linux Kernel) state machine.
5078 *
5079 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
5080 * the driver.
5081 *
5082 */
5083
5084 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
5085 }
5086 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5087 pAdapterNode = pNext;
5088 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
5089
5090
5091 /* Free the allocated management frame */
5092 kfree(mgmt);
5093
5094 /* Retry until we unload or reach max count */
5095 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
5096 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
5097
5098 return status;
5099
5100}
5101/**---------------------------------------------------------------------------
5102 *
5103 * \brief wlan_hdd_restart_timer_cb
5104 *
5105 * Restart timer callback. An internal function.
5106 *
5107 * \param - User data:
5108 *
5109 * \return - None
5110 *
5111 * --------------------------------------------------------------------------*/
5112
5113void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
5114{
5115 hdd_context_t *pHddCtx = usrDataForCallback;
5116 wlan_hdd_framework_restart(pHddCtx);
5117 return;
5118
5119}
5120
5121
5122/**---------------------------------------------------------------------------
5123 *
5124 * \brief wlan_hdd_restart_driver
5125 *
5126 * This function sends an event to supplicant to restart the WLAN driver.
5127 *
5128 * This function is called from vos_wlanRestart.
5129 *
5130 * \param - pHddCtx
5131 *
5132 * \return - VOS_STATUS_SUCCESS: Success
5133 * VOS_STATUS_E_EMPTY: Adapter is Empty
5134 * VOS_STATUS_E_ALREADY: Request already in progress
5135
5136 * --------------------------------------------------------------------------*/
5137VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
5138{
5139 VOS_STATUS status = VOS_STATUS_SUCCESS;
5140
5141 /* A tight check to make sure reentrancy */
5142 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
5143 {
5144 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
5145 "%s: WLAN restart is already in progress", __func__);
5146
5147 return VOS_STATUS_E_ALREADY;
5148 }
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005149 /* when WLAN driver is statically linked, then invoke SSR by sending
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005150 * the reset interrupt. If it is DLKM, then use restart API
5151 */
5152#ifdef MODULE
Jeff Johnsone7245742012-09-05 17:12:55 -07005153 status = wlan_hdd_framework_restart(pHddCtx);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005154#else
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005155#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005156 wcnss_reset_intr();
5157#endif
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005158#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005159
Jeff Johnsone7245742012-09-05 17:12:55 -07005160 return status;
5161}
5162
5163
Jeff Johnson295189b2012-06-20 16:38:30 -07005164//Register the module init/exit functions
5165module_init(hdd_module_init);
5166module_exit(hdd_module_exit);
5167
5168MODULE_LICENSE("Dual BSD/GPL");
5169MODULE_AUTHOR("Qualcomm Atheros, Inc.");
5170MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
5171
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005172module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
5173 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07005174
5175module_param_call(fwpath, fwpath_changed_handler, param_get_string, fwpath,
5176 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);