blob: 868950b461ad16d7647cacb4be578b28b27a2c8f [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* wlan_hdd_early_suspend.c
44*
45* \brief power management functions
46*
47* Description
48* Copyright 2009 (c) Qualcomm, Incorporated.
49* All Rights Reserved.
50* Qualcomm Confidential and Proprietary.
51*
52==============================================================================**/
53/* $HEADER$ */
54
55/**-----------------------------------------------------------------------------
56* Include files
57* ----------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -070058
59#include <linux/pm.h>
60#include <linux/wait.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070061#include <wlan_hdd_includes.h>
62#include <wlan_qct_driver.h>
63#include <linux/wakelock.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070064
65#include "halTypes.h"
66#include "sme_Api.h"
67#include <vos_api.h>
68#include "vos_power.h"
69#include <vos_sched.h>
70#include <macInitApi.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070071#include <wlan_qct_sys.h>
72#include <wlan_btc_svc.h>
73#include <wlan_nlink_common.h>
74#include <wlan_hdd_main.h>
75#include <wlan_hdd_assoc.h>
76#include <wlan_hdd_dev_pwr.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070077#include <wlan_nlink_srv.h>
78#include <wlan_hdd_misc.h>
79
Jeff Johnson295189b2012-06-20 16:38:30 -070080#include <linux/semaphore.h>
81#include <wlan_hdd_hostapd.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070082#include "cfgApi.h"
83
84#ifdef WLAN_BTAMP_FEATURE
85#include "bapApi.h"
86#include "bap_hdd_main.h"
87#include "bap_hdd_misc.h"
88#endif
89
Jeff Johnsone7245742012-09-05 17:12:55 -070090#include <linux/wcnss_wlan.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070091#include <linux/inetdevice.h>
92#include <wlan_hdd_cfg.h>
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053093#include <wlan_hdd_cfg80211.h>
Gopichand Nakkala746a9452013-06-11 12:45:54 +053094#include <net/addrconf.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070095/**-----------------------------------------------------------------------------
96* Preprocessor definitions and constants
97* ----------------------------------------------------------------------------*/
98
99/**-----------------------------------------------------------------------------
100* Type declarations
101* ----------------------------------------------------------------------------*/
102
103/**-----------------------------------------------------------------------------
104* Function and variables declarations
105* ----------------------------------------------------------------------------*/
106#include "wlan_hdd_power.h"
107#include "wlan_hdd_packet_filtering.h"
108
Sameer Thalappile5637f42013-08-07 15:46:55 -0700109#define HDD_SSR_BRING_UP_TIME 180000
Jeff Johnson295189b2012-06-20 16:38:30 -0700110
111static eHalStatus g_full_pwr_status;
112static eHalStatus g_standby_status;
113
114extern VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx);
115extern VOS_STATUS vos_chipExitDeepSleepVREGHandler(
116 vos_call_status_type* status,
117 vos_power_cb_type callback,
118 v_PVOID_t user_data);
119extern void hdd_wlan_initial_scan(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700120
121extern struct notifier_block hdd_netdev_notifier;
Jeff Johnson295189b2012-06-20 16:38:30 -0700122extern tVOS_CON_MODE hdd_get_conparam ( void );
Jeff Johnson295189b2012-06-20 16:38:30 -0700123
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -0700124static struct timer_list ssr_timer;
125static bool ssr_timer_started;
Jeff Johnson295189b2012-06-20 16:38:30 -0700126
127//Callback invoked by PMC to report status of standby request
128void hdd_suspend_standby_cbk (void *callbackContext, eHalStatus status)
129{
130 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
131 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Standby status = %d", __func__, status);
132 g_standby_status = status;
133
134 if(eHAL_STATUS_SUCCESS == status)
135 {
136 pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY;
137 }
138 else
139 {
140 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__);
141 }
142
143 complete(&pHddCtx->standby_comp_var);
144}
145
146//Callback invoked by PMC to report status of full power request
147void hdd_suspend_full_pwr_callback(void *callbackContext, eHalStatus status)
148{
149 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
150 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Full Power status = %d", __func__, status);
151 g_full_pwr_status = status;
152
153 if(eHAL_STATUS_SUCCESS == status)
154 {
155 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
156 }
157 else
158 {
159 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
160 }
161
162 complete(&pHddCtx->full_pwr_comp_var);
163}
164
165eHalStatus hdd_exit_standby(hdd_context_t *pHddCtx)
166{
167 eHalStatus status = VOS_STATUS_SUCCESS;
c_hpothuffdb5272013-10-02 16:42:35 +0530168 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -0700169
170 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from standby",__func__);
171 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
172
173 g_full_pwr_status = eHAL_STATUS_FAILURE;
174 status = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback, pHddCtx,
175 eSME_FULL_PWR_NEEDED_BY_HDD);
176
177 if(status == eHAL_STATUS_PMC_PENDING)
178 {
179 //Block on a completion variable. Can't wait forever though
c_hpothuffdb5272013-10-02 16:42:35 +0530180 ret = wait_for_completion_interruptible_timeout(
181 &pHddCtx->full_pwr_comp_var,
182 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
183 if (0 >= ret)
184 {
185 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:wait on full_pwr_comp_var failed %ld",
186 __func__, ret);
187 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700188 status = g_full_pwr_status;
189 if(g_full_pwr_status != eHAL_STATUS_SUCCESS)
190 {
191 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
192 VOS_ASSERT(0);
193 goto failure;
194 }
195 }
196 else if(status != eHAL_STATUS_SUCCESS)
197 {
198 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d",
199 __func__, status);
200 VOS_ASSERT(0);
201 goto failure;
202 }
203 else
204 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
205
206failure:
207 //No blocking to reduce latency. No other device should be depending on WLAN
208 //to finish resume and WLAN won't be instantly on after resume
209 return status;
210}
211
212
213//Helper routine to put the chip into standby
214VOS_STATUS hdd_enter_standby(hdd_context_t *pHddCtx)
215{
216 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
217 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
c_hpothuffdb5272013-10-02 16:42:35 +0530218 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -0700219
220 //Disable IMPS/BMPS as we do not want the device to enter any power
221 //save mode on its own during suspend sequence
222 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
223 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
224
225 //Note we do not disable queues unnecessarily. Queues should already be disabled
226 //if STA is disconnected or the queue will be disabled as and when disconnect
227 //happens because of standby procedure.
228
229 //Ensure that device is in full power first. There is scope for optimization
230 //here especially in scenarios where PMC is already in IMPS or REQUEST_IMPS.
231 //Core s/w needs to be optimized to handle this. Until then we request full
232 //power before issuing request for standby.
233 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
234 g_full_pwr_status = eHAL_STATUS_FAILURE;
235 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback,
236 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
237
238 if(halStatus == eHAL_STATUS_PMC_PENDING)
239 {
240 //Block on a completion variable. Can't wait forever though
c_hpothuffdb5272013-10-02 16:42:35 +0530241 ret = wait_for_completion_interruptible_timeout(
242 &pHddCtx->full_pwr_comp_var,
243 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
244 if (0 >= ret)
245 {
246 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:wait on full_pwr_comp_var failed %ld",
247 __func__, ret);
248 }
249
Jeff Johnson295189b2012-06-20 16:38:30 -0700250 if(g_full_pwr_status != eHAL_STATUS_SUCCESS)
251 {
252 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower Failed",__func__);
253 VOS_ASSERT(0);
254 vosStatus = VOS_STATUS_E_FAILURE;
255 goto failure;
256 }
257 }
258 else if(halStatus != eHAL_STATUS_SUCCESS)
259 {
260 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d",
261 __func__, halStatus);
262 VOS_ASSERT(0);
263 vosStatus = VOS_STATUS_E_FAILURE;
264 goto failure;
265 }
266
267 if(pHddCtx->hdd_mcastbcast_filter_set == TRUE) {
268 hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
269 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
270 }
271
272 //Request standby. Standby will cause the STA to disassociate first. TX queues
273 //will be disabled (by HDD) when STA disconnects. You do not want to disable TX
274 //queues here. Also do not assert if the failure code is eHAL_STATUS_PMC_NOT_NOW as PMC
275 //will send this failure code in case of concurrent sessions. Power Save cannot be supported
276 //when there are concurrent sessions.
277 INIT_COMPLETION(pHddCtx->standby_comp_var);
278 g_standby_status = eHAL_STATUS_FAILURE;
279 halStatus = sme_RequestStandby(pHddCtx->hHal, hdd_suspend_standby_cbk, pHddCtx);
280
281 if (halStatus == eHAL_STATUS_PMC_PENDING)
282 {
283 //Wait till WLAN device enters standby mode
c_hpothuffdb5272013-10-02 16:42:35 +0530284 ret = wait_for_completion_timeout(&pHddCtx->standby_comp_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700285 msecs_to_jiffies(WLAN_WAIT_TIME_STANDBY));
c_hpothuffdb5272013-10-02 16:42:35 +0530286 if (0 >= ret)
287 {
288 hddLog(VOS_TRACE_LEVEL_ERROR,
289 FL("wait on standby_comp_var failed %ld"), ret);
290 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700291 if (g_standby_status != eHAL_STATUS_SUCCESS && g_standby_status != eHAL_STATUS_PMC_NOT_NOW)
292 {
293 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__);
294 VOS_ASSERT(0);
295 vosStatus = VOS_STATUS_E_FAILURE;
296 goto failure;
297 }
298 }
299 else if (halStatus != eHAL_STATUS_SUCCESS && halStatus != eHAL_STATUS_PMC_NOT_NOW) {
300 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed - status %d",
301 __func__, halStatus);
302 VOS_ASSERT(0);
303 vosStatus = VOS_STATUS_E_FAILURE;
304 goto failure;
305 }
306 else
307 pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY;
308
309failure:
310 //Restore IMPS config
311 if(pHddCtx->cfg_ini->fIsImpsEnabled)
312 sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
313
314 //Restore BMPS config
315 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
316 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
317
318 return vosStatus;
319}
320
321
322//Helper routine for Deep sleep entry
323VOS_STATUS hdd_enter_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter)
324{
325 eHalStatus halStatus;
326 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
327 vos_call_status_type callType;
c_hpothuffdb5272013-10-02 16:42:35 +0530328 long ret;
Jeff Johnsonbc676b42013-02-14 16:04:08 -0800329
Jeff Johnson295189b2012-06-20 16:38:30 -0700330 //Stop the Interface TX queue.
331 netif_tx_disable(pAdapter->dev);
332 netif_carrier_off(pAdapter->dev);
333
334 //Disable IMPS,BMPS as we do not want the device to enter any power
335 //save mode on it own during suspend sequence
336 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
337 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
338
339 //Ensure that device is in full power as we will touch H/W during vos_Stop
340 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
341 g_full_pwr_status = eHAL_STATUS_FAILURE;
342 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback,
343 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
344
345 if(halStatus == eHAL_STATUS_PMC_PENDING)
346 {
347 //Block on a completion variable. Can't wait forever though
c_hpothuffdb5272013-10-02 16:42:35 +0530348 ret = wait_for_completion_interruptible_timeout(
349 &pHddCtx->full_pwr_comp_var,
350 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
351 if (0 >= ret)
352 {
353 hddLog(VOS_TRACE_LEVEL_ERROR,
354 FL("wait on full_pwr_comp_var failed %ld"), ret);
355 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700356 if(g_full_pwr_status != eHAL_STATUS_SUCCESS){
357 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
358 VOS_ASSERT(0);
359 }
360 }
361 else if(halStatus != eHAL_STATUS_SUCCESS)
362 {
363 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Request for Full Power failed",__func__);
364 VOS_ASSERT(0);
365 }
366
367 //Issue a disconnect. This is required to inform the supplicant that
368 //STA is getting disassociated and for GUI to be updated properly
369 INIT_COMPLETION(pAdapter->disconnect_comp_var);
370 halStatus = sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED);
371
372 //Success implies disconnect command got queued up successfully
373 if(halStatus == eHAL_STATUS_SUCCESS)
374 {
375 //Block on a completion variable. Can't wait forever though.
c_hpothuffdb5272013-10-02 16:42:35 +0530376 ret = wait_for_completion_interruptible_timeout(
377 &pAdapter->disconnect_comp_var,
378 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
379 if (0 >= ret)
380 {
381 hddLog(VOS_TRACE_LEVEL_ERROR,
382 FL("wait on disconnect_comp_var failed %ld"), ret);
383 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700384 }
385
386
387 //None of the steps should fail after this. Continue even in case of failure
388 vosStatus = vos_stop( pHddCtx->pvosContext );
c_hpothuffdb5272013-10-02 16:42:35 +0530389 if( !VOS_IS_STATUS_SUCCESS( vosStatus ))
390 {
391 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: vos_stop return failed %d",
392 __func__, vosStatus);
393 VOS_ASSERT(0);
394 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700395
Jeff Johnson295189b2012-06-20 16:38:30 -0700396 vosStatus = vos_chipAssertDeepSleep( &callType, NULL, NULL );
c_hpothuffdb5272013-10-02 16:42:35 +0530397 if( VOS_IS_STATUS_SUCCESS( vosStatus ))
398 {
399 hddLog(VOS_TRACE_LEVEL_ERROR,
400 FL("vos_chipAssertDeepSleep return failed %d"), vosStatus);
401 VOS_ASSERT(0);
402 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700403
404 //Vote off any PMIC voltage supplies
405 vosStatus = vos_chipPowerDown(NULL, NULL, NULL);
c_hpothuffdb5272013-10-02 16:42:35 +0530406 if( !VOS_IS_STATUS_SUCCESS( vosStatus ))
407 {
408 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: vos_chipPowerDown return failed %d",
409 __func__, vosStatus);
410 VOS_ASSERT(0);
411 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700412
Jeff Johnson295189b2012-06-20 16:38:30 -0700413 pHddCtx->hdd_ps_state = eHDD_SUSPEND_DEEP_SLEEP;
414
415 //Restore IMPS config
416 if(pHddCtx->cfg_ini->fIsImpsEnabled)
417 sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
418
419 //Restore BMPS config
420 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
421 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
422
Jeff Johnson295189b2012-06-20 16:38:30 -0700423 return vosStatus;
424}
425
426VOS_STATUS hdd_exit_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter)
427{
428 VOS_STATUS vosStatus;
429 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -0700430
431 //Power Up Libra WLAN card first if not already powered up
432 vosStatus = vos_chipPowerUp(NULL,NULL,NULL);
433 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
434 {
c_hpothuffdb5272013-10-02 16:42:35 +0530435 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN not Powered Up."
Jeff Johnson295189b2012-06-20 16:38:30 -0700436 "exiting", __func__);
437 goto err_deep_sleep;
438 }
439
Jeff Johnson295189b2012-06-20 16:38:30 -0700440 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
441 "%s: calling hdd_set_sme_config",__func__);
442 vosStatus = hdd_set_sme_config( pHddCtx );
443 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
444 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
445 {
446 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
447 "%s: Failed in hdd_set_sme_config",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700448 goto err_deep_sleep;
Jeff Johnson295189b2012-06-20 16:38:30 -0700449 }
450
451 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
452 "%s: calling vos_start",__func__);
453 vosStatus = vos_start( pHddCtx->pvosContext );
454 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
455 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
456 {
457 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
458 "%s: Failed in vos_start",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700459 goto err_deep_sleep;
Jeff Johnson295189b2012-06-20 16:38:30 -0700460 }
461
462 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
463 "%s: calling hdd_post_voss_start_config",__func__);
464 vosStatus = hdd_post_voss_start_config( pHddCtx );
465 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
466 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
467 {
468 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
469 "%s: Failed in hdd_post_voss_start_config",__func__);
470 goto err_voss_stop;
471 }
472
473
474 //Open a SME session for future operation
475 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pHddCtx,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -0700476 (tANI_U8 *)&pAdapter->macAddressCurrent,
477 &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700478 if ( !HAL_STATUS_SUCCESS( halStatus ) )
479 {
Jeff Johnson0299d0a2013-10-30 12:37:43 -0700480 hddLog(VOS_TRACE_LEVEL_FATAL,"sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -0700481 halStatus, halStatus );
482 goto err_voss_stop;
483
484 }
485
486 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
487
488 //Trigger the initial scan
489 hdd_wlan_initial_scan(pHddCtx);
490
491 return VOS_STATUS_SUCCESS;
492
493err_voss_stop:
494 vos_stop(pHddCtx->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -0700495err_deep_sleep:
496 return VOS_STATUS_E_FAILURE;
497
498}
499
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530500/*
501 * Function: hdd_conf_hostoffload
502 * Central function to configure the supported offloads,
503 * either enable or disable them.
504 */
505void hdd_conf_hostoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
506{
507 hdd_context_t *pHddCtx = NULL;
508 v_CONTEXT_t *pVosContext = NULL;
509 VOS_STATUS vstatus = VOS_STATUS_E_FAILURE;
510
511 hddLog(VOS_TRACE_LEVEL_INFO, FL("Configuring offloads with flag: %d"),
512 fenable);
513
514 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
515
516 if (NULL == pVosContext)
517 {
518 hddLog(VOS_TRACE_LEVEL_ERROR, FL(" Global VOS context is Null"));
519 return;
520 }
521
522 //Get the HDD context.
523 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
524
525 if (NULL == pHddCtx)
526 {
527 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: HDD context is Null", __func__);
528 return;
529 }
530
531 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
532 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
533 {
534 if (fenable)
535 {
536 if (eConnectionState_Associated ==
537 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)
538 {
539 if ((pHddCtx->cfg_ini->fhostArpOffload))
540 {
541 /*
542 * Configure the ARP Offload.
543 * Even if it fails we have to reconfigure the MC/BC
544 * filter flag as we want RIVA not to drop BroadCast
545 * Packets
546 */
547 hddLog(VOS_TRACE_LEVEL_INFO,
548 FL("Calling ARP Offload with flag: %d"), fenable);
549 vstatus = hdd_conf_arp_offload(pAdapter, fenable);
550 pHddCtx->configuredMcastBcastFilter &=
551 ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST);
552
553 if (!VOS_IS_STATUS_SUCCESS(vstatus))
554 {
555 hddLog(VOS_TRACE_LEVEL_ERROR,
556 "Failed to enable ARPOFfloadFeature %d",
557 vstatus);
558 }
559 }
560 //Configure GTK_OFFLOAD
561#ifdef WLAN_FEATURE_GTK_OFFLOAD
562 hdd_conf_gtk_offload(pAdapter, fenable);
563#endif
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530564
565#ifdef WLAN_NS_OFFLOAD
566 if (pHddCtx->cfg_ini->fhostNSOffload)
567 {
568 /*
569 * Configure the NS Offload.
570 * Even if it fails we have to reconfigure the MC/BC filter flag
571 * as we want RIVA not to drop Multicast Packets
572 */
573
574 hddLog(VOS_TRACE_LEVEL_INFO,
575 FL("Calling NS Offload with flag: %d"), fenable);
576 hdd_conf_ns_offload(pAdapter, fenable);
577 pHddCtx->configuredMcastBcastFilter &=
578 ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST);
579 }
580#endif
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530581 }
582 }
583 else
584 {
585 //Disable ARPOFFLOAD
586 if (pHddCtx->cfg_ini->fhostArpOffload)
587 {
588 vstatus = hdd_conf_arp_offload(pAdapter, fenable);
589 if (!VOS_IS_STATUS_SUCCESS(vstatus))
590 {
591 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530592 "Failed to disable ARPOffload Feature %d", vstatus);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530593 }
594 }
595 //Disable GTK_OFFLOAD
596#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530597 hdd_conf_gtk_offload(pAdapter, fenable);
598#endif
599
600#ifdef WLAN_NS_OFFLOAD
601 //Disable NSOFFLOAD
602 if (pHddCtx->cfg_ini->fhostNSOffload)
603 {
604 hdd_conf_ns_offload(pAdapter, fenable);
605 }
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530606#endif
607 }
608 }
609 return;
610}
611
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530612#ifdef WLAN_NS_OFFLOAD
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530613void hdd_ipv6_notifier_work_queue(struct work_struct *work)
614{
615 hdd_adapter_t* pAdapter =
616 container_of(work, hdd_adapter_t, ipv6NotifierWorkQueue);
617 hdd_context_t *pHddCtx;
618 int status;
619
620 hddLog(LOG1, FL("Reconfiguring NS Offload"));
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530621
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530622 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
623 status = wlan_hdd_validate_context(pHddCtx);
624 if (0 != status)
625 {
626 hddLog(LOGE, FL("HDD context is invalid"));
627 return;
628 }
629
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530630 if ((eConnectionState_Associated ==
631 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)
632 && (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid))
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530633 {
634 // This invocation being part of the IPv6 registration callback,
635 // we are passing second parameter as 2 to avoid registration
636 // of IPv6 notifier again.
637 hdd_conf_ns_offload(pAdapter, 2);
638 }
639}
640
641static int wlan_hdd_ipv6_changed(struct notifier_block *nb,
642 unsigned long data, void *arg)
643{
644 struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)arg;
645 struct net_device *ndev = ifa->idev->dev;
646 hdd_adapter_t *pAdapter =
647 container_of(nb, struct hdd_adapter_s, ipv6_notifier);
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530648 hdd_context_t *pHddCtx;
649 int status;
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530650
651 if (pAdapter && pAdapter->dev == ndev)
652 {
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530653 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
654 status = wlan_hdd_validate_context(pHddCtx);
655 if (0 != status)
656 {
657 hddLog(LOGE, FL("HDD context is invalid"));
658 return NOTIFY_DONE;
659 }
660
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530661 schedule_work(&pAdapter->ipv6NotifierWorkQueue);
662 }
663
664 return NOTIFY_DONE;
665}
666
667/**----------------------------------------------------------------------------
668
669 \brief hdd_conf_ns_offload() - Configure NS offload
670
671 Called during SUSPEND to configure the NS offload (MC BC filter) which
672 reduces power consumption.
673
674 \param - pAdapter - Adapter context for which NS offload is to be configured
675 \param - fenable - 0 - disable.
676 1 - enable. (with IPv6 notifier registration)
677 2 - enable. (without IPv6 notifier registration)
678
679 \return - void
680
681 ---------------------------------------------------------------------------*/
682void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, int fenable)
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530683{
684 struct inet6_dev *in6_dev;
685 struct inet6_ifaddr *ifp;
686 struct list_head *p;
687 tANI_U8 selfIPv6Addr[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA][SIR_MAC_IPV6_ADDR_LEN] = {{0,}};
688 tANI_BOOLEAN selfIPv6AddrValid[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA] = {0};
689 tSirHostOffloadReq offLoadRequest;
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530690 hdd_context_t *pHddCtx;
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530691
692 int i =0;
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530693 int ret =0;
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530694 eHalStatus returnStatus;
695
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530696 ENTER();
697 hddLog(LOG1, FL(" fenable = %d"), fenable);
698
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530699 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
700
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530701 if (fenable)
702 {
703 in6_dev = __in6_dev_get(pAdapter->dev);
704 if (NULL != in6_dev)
705 {
706 //read_lock_bh(&in6_dev->lock);
707 list_for_each(p, &in6_dev->addr_list)
708 {
709 ifp = list_entry(p, struct inet6_ifaddr, if_list);
710 switch(ipv6_addr_src_scope(&ifp->addr))
711 {
712 case IPV6_ADDR_SCOPE_LINKLOCAL:
713 vos_mem_copy(&selfIPv6Addr[0], &ifp->addr.s6_addr,
714 sizeof(ifp->addr.s6_addr));
715 selfIPv6AddrValid[0] = SIR_IPV6_ADDR_VALID;
Hardik Kantilal Patel1341bdf2013-08-22 20:27:15 +0530716 hddLog (VOS_TRACE_LEVEL_INFO,
717 "Found IPV6_ADDR_SCOPE_LINKLOCAL Address : %pI6",
718 selfIPv6Addr[0]);
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530719 break;
720 case IPV6_ADDR_SCOPE_GLOBAL:
721 vos_mem_copy(&selfIPv6Addr[1], &ifp->addr.s6_addr,
722 sizeof(ifp->addr.s6_addr));
Hardik Kantilal Patel1341bdf2013-08-22 20:27:15 +0530723 selfIPv6AddrValid[1] = SIR_IPV6_ADDR_VALID;
724 hddLog (VOS_TRACE_LEVEL_INFO,
725 "Found IPV6_ADDR_SCOPE_GLOBAL Address : %pI6",
726 selfIPv6Addr[1]);
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530727 break;
728 default:
729 hddLog(LOGE, "The Scope %d is not supported",
730 ipv6_addr_src_scope(&ifp->addr));
731 }
732
733 }
734 //read_unlock_bh(&in6_dev->lock);
735 vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest));
736 for (i =0; i<SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA; i++)
737 {
738 if (selfIPv6AddrValid[i])
739 {
740 //Filling up the request structure
741 /* Filling the selfIPv6Addr with solicited address
742 * A Solicited-Node multicast address is created by
743 * taking the last 24 bits of a unicast or anycast
744 * address and appending them to the prefix
745 *
746 * FF02:0000:0000:0000:0000:0001:FFXX:XX
747 *
748 * here XX is the unicast/anycast bits
749 */
750 offLoadRequest.nsOffloadInfo.selfIPv6Addr[0] = 0xFF;
751 offLoadRequest.nsOffloadInfo.selfIPv6Addr[1] = 0x02;
752 offLoadRequest.nsOffloadInfo.selfIPv6Addr[11] = 0x01;
753 offLoadRequest.nsOffloadInfo.selfIPv6Addr[12] = 0xFF;
754 offLoadRequest.nsOffloadInfo.selfIPv6Addr[13] = selfIPv6Addr[i][13];
755 offLoadRequest.nsOffloadInfo.selfIPv6Addr[14] = selfIPv6Addr[i][14];
756 offLoadRequest.nsOffloadInfo.selfIPv6Addr[15] = selfIPv6Addr[i][15];
757 offLoadRequest.nsOffloadInfo.slotIdx = i;
758
759 vos_mem_copy(&offLoadRequest.nsOffloadInfo.targetIPv6Addr[0],
760 &selfIPv6Addr[i][0], sizeof(tANI_U8)*SIR_MAC_IPV6_ADDR_LEN);
761 vos_mem_copy(&offLoadRequest.nsOffloadInfo.selfMacAddr,
762 &pAdapter->macAddressCurrent.bytes,
763 sizeof(tANI_U8)*SIR_MAC_ADDR_LEN);
764
765 offLoadRequest.nsOffloadInfo.targetIPv6AddrValid[0] = SIR_IPV6_ADDR_VALID;
766 offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD;
767 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
768
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530769 hddLog (VOS_TRACE_LEVEL_INFO,
770 "configuredMcastBcastFilter: %d",pHddCtx->configuredMcastBcastFilter);
771
Kiet Lamc8e1eb52013-10-24 00:30:49 +0530772 if ((VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid)
773 && ((HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST ==
774 pHddCtx->sus_res_mcastbcast_filter) ||
775 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
776 pHddCtx->sus_res_mcastbcast_filter)))
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530777 {
778 hddLog (VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -0800779 "Set offLoadRequest with SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE");
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530780 offLoadRequest.enableOrDisable =
781 SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE;
782 }
783
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530784 vos_mem_copy(&offLoadRequest.params.hostIpv6Addr,
785 &offLoadRequest.nsOffloadInfo.targetIPv6Addr[0],
786 sizeof(tANI_U8)*SIR_MAC_IPV6_ADDR_LEN);
787
788 hddLog (VOS_TRACE_LEVEL_INFO,
789 "Setting NSOffload with solicitedIp: %pI6, targetIp: %pI6",
790 offLoadRequest.nsOffloadInfo.selfIPv6Addr,
791 offLoadRequest.nsOffloadInfo.targetIPv6Addr[0]);
792
793 //Configure the Firmware with this
794 returnStatus = sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
795 pAdapter->sessionId, &offLoadRequest);
796 if(eHAL_STATUS_SUCCESS != returnStatus)
797 {
798 hddLog(VOS_TRACE_LEVEL_ERROR,
799 FL("Failed to enable HostOffload feature with status: %d"),
800 returnStatus);
801 }
802 vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest));
803 }
804 }
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530805 if (fenable == 1 && !pAdapter->ipv6_notifier_registered)
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530806 {
807 // Register IPv6 notifier to notify if any change in IP
808 // So that we can reconfigure the offload parameters
809 pAdapter->ipv6_notifier.notifier_call =
810 wlan_hdd_ipv6_changed;
811 ret = register_inet6addr_notifier(&pAdapter->ipv6_notifier);
812 if (ret)
813 {
814 hddLog(LOGE, FL("Failed to register IPv6 notifier"));
815 }
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530816 else
817 {
818 hddLog(LOG1, FL("Registered IPv6 notifier"));
819 pAdapter->ipv6_notifier_registered = true;
820 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530821 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530822 }
823 else
824 {
825 hddLog(VOS_TRACE_LEVEL_ERROR,
826 FL("IPv6 dev does not exist. Failed to request NSOffload"));
827 return;
828 }
829 }
830 else
831 {
832 //Disable NSOffload
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530833 if (pAdapter->ipv6_notifier_registered)
834 {
835 hddLog(LOG1, FL("Unregistered IPv6 notifier"));
836 unregister_inet6addr_notifier(&pAdapter->ipv6_notifier);
837 pAdapter->ipv6_notifier_registered = false;
838 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530839 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
840 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
841 offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD;
842
Vinay Krishna Erannab29c6142014-01-07 12:20:51 +0530843 //Disable NSOffload on all slots
844 for (i = 0; i<SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA; i++)
845 {
846 offLoadRequest.nsOffloadInfo.slotIdx = i;
847 if (eHAL_STATUS_SUCCESS !=
Vinay Krishna Eranna911a3b82014-01-07 12:20:51 +0530848 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
849 pAdapter->sessionId, &offLoadRequest))
Vinay Krishna Erannab29c6142014-01-07 12:20:51 +0530850 {
851 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to disable NSOflload"
852 " on slot %d"), i);
853 }
854 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530855 }
856 return;
857}
858#endif
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530859
860void hdd_ipv4_notifier_work_queue(struct work_struct *work)
861{
862 hdd_adapter_t* pAdapter =
863 container_of(work, hdd_adapter_t, ipv4NotifierWorkQueue);
864 hdd_context_t *pHddCtx;
865 int status;
866
867 hddLog(LOG1, FL("Reconfiguring ARP Offload"));
868 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
869 status = wlan_hdd_validate_context(pHddCtx);
870 if (0 != status)
871 {
872 hddLog(LOGE, FL("HDD context is invalid"));
873 return;
874 }
875
876 if ((eConnectionState_Associated ==
877 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)
878 && (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid))
879 {
880 // This invocation being part of the IPv4 registration callback,
881 // we are passing second parameter as 2 to avoid registration
882 // of IPv4 notifier again.
883 hdd_conf_arp_offload(pAdapter, 2);
884 }
885}
886
887static int wlan_hdd_ipv4_changed(struct notifier_block *nb,
888 unsigned long data, void *arg)
889{
890 struct in_ifaddr *ifa = (struct in_ifaddr *)arg;
891 struct in_ifaddr **ifap = NULL;
892 struct in_device *in_dev;
893
894 struct net_device *ndev = ifa->ifa_dev->dev;
895 hdd_adapter_t *pAdapter =
896 container_of(nb, struct hdd_adapter_s, ipv4_notifier);
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +0530897 hdd_context_t *pHddCtx;
898 int status;
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530899 if (pAdapter && pAdapter->dev == ndev)
900 {
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +0530901 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
902 status = wlan_hdd_validate_context(pHddCtx);
903 if (0 != status)
904 {
905 hddLog(LOGE, FL("HDD context is invalid"));
906 return NOTIFY_DONE;
907 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530908 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
909 {
910 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
911 ifap = &ifa->ifa_next)
912 {
913 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
914 {
915 break; /* found */
916 }
917 }
918 }
919 if(ifa && ifa->ifa_local)
920 {
921 schedule_work(&pAdapter->ipv4NotifierWorkQueue);
922 }
923 }
924
925 return NOTIFY_DONE;
926}
927
928/**----------------------------------------------------------------------------
929
930 \brief hdd_conf_arp_offload() - Configure ARP offload
931
932 Called during SUSPEND to configure the ARP offload (MC BC filter) which
933 reduces power consumption.
934
935 \param - pAdapter -Adapter context for which ARP offload is to be configured
936 \param - fenable - 0 - disable.
937 1 - enable. (with IPv4 notifier registration)
938 2 - enable. (without IPv4 notifier registration)
939
940 \return -
941 VOS_STATUS_SUCCESS - on successful operation
942 VOS_STATUS_E_FAILURE - on failure of operation
943-----------------------------------------------------------------------------*/
944VOS_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, int fenable)
Jeff Johnson295189b2012-06-20 16:38:30 -0700945{
946 struct in_ifaddr **ifap = NULL;
947 struct in_ifaddr *ifa = NULL;
948 struct in_device *in_dev;
949 int i = 0;
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530950 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700951 tSirHostOffloadReq offLoadRequest;
Yathish9f22e662012-12-10 14:21:35 -0800952 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700953
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530954 hddLog(VOS_TRACE_LEVEL_ERROR, FL(" fenable = %d \n"), fenable);
Jeff Johnson295189b2012-06-20 16:38:30 -0700955
Jeff Johnson295189b2012-06-20 16:38:30 -0700956 if(fenable)
957 {
958 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
959 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530960 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700961 ifap = &ifa->ifa_next)
962 {
963 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
964 {
965 break; /* found */
966 }
967 }
968 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700969 if(ifa && ifa->ifa_local)
970 {
971 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
972 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
973
Arif Hussain6d2a3322013-11-17 19:50:10 -0800974 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700975
Amar Singhald53568e2013-09-26 11:03:45 -0700976 if (((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
977 pHddCtx->sus_res_mcastbcast_filter) ||
978 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
979 pHddCtx->sus_res_mcastbcast_filter)) &&
980 (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid))
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700981 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530982 offLoadRequest.enableOrDisable =
Amar Singhald53568e2013-09-26 11:03:45 -0700983 SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
984 hddLog(VOS_TRACE_LEVEL_INFO,
985 "offload: inside arp offload conditional check");
Jeff Johnson295189b2012-06-20 16:38:30 -0700986 }
Amar Singhald53568e2013-09-26 11:03:45 -0700987
988 hddLog(VOS_TRACE_LEVEL_INFO, "offload: arp filter programmed = %d",
989 offLoadRequest.enableOrDisable);
990
Jeff Johnson295189b2012-06-20 16:38:30 -0700991 //converting u32 to IPV4 address
992 for(i = 0 ; i < 4; i++)
993 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530994 offLoadRequest.params.hostIpv4Addr[i] =
Jeff Johnson295189b2012-06-20 16:38:30 -0700995 (ifa->ifa_local >> (i*8) ) & 0xFF ;
996 }
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530997 hddLog(VOS_TRACE_LEVEL_INFO, " Enable SME HostOffload: %d.%d.%d.%d",
Jeff Johnson295189b2012-06-20 16:38:30 -0700998 offLoadRequest.params.hostIpv4Addr[0],
999 offLoadRequest.params.hostIpv4Addr[1],
1000 offLoadRequest.params.hostIpv4Addr[2],
1001 offLoadRequest.params.hostIpv4Addr[3]);
1002
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301003 if (eHAL_STATUS_SUCCESS !=
1004 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1005 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -07001006 {
1007 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to enable HostOffload "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001008 "feature", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001009 return VOS_STATUS_E_FAILURE;
1010 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001011 }
1012 else
1013 {
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301014 hddLog(VOS_TRACE_LEVEL_INFO, FL("IP Address is not assigned\n"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001015 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301016
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05301017 if (fenable == 1 && !pAdapter->ipv4_notifier_registered)
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301018 {
1019 // Register IPv4 notifier to notify if any change in IP
1020 // So that we can reconfigure the offload parameters
1021 pAdapter->ipv4_notifier.notifier_call =
1022 wlan_hdd_ipv4_changed;
1023 ret = register_inetaddr_notifier(&pAdapter->ipv4_notifier);
1024 if (ret)
1025 {
1026 hddLog(LOGE, FL("Failed to register IPv4 notifier"));
1027 }
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05301028 else
1029 {
1030 hddLog(LOG1, FL("Registered IPv4 notifier"));
1031 pAdapter->ipv4_notifier_registered = true;
1032 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301033 }
1034 return VOS_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07001035 }
1036 else
1037 {
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05301038 if (pAdapter->ipv4_notifier_registered)
1039 {
1040 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
1041 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
1042 pAdapter->ipv4_notifier_registered = false;
1043 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001044 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
1045 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
1046 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
1047
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301048 if (eHAL_STATUS_SUCCESS !=
1049 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1050 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -07001051 {
1052 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to disable host "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001053 "offload feature", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001054 return VOS_STATUS_E_FAILURE;
1055 }
1056 return VOS_STATUS_SUCCESS;
1057 }
1058}
1059
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301060/*
1061 * This function is called before setting mcbc filters
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301062 * to modify filter value considering Different Offloads
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301063*/
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301064void hdd_mcbc_filter_modification(hdd_context_t* pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301065 tANI_U8 *pMcBcFilter)
1066{
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301067 if (NULL == pHddCtx)
1068 {
1069 hddLog(VOS_TRACE_LEVEL_ERROR, FL("NULL HDD context passed"));
1070 return;
1071 }
1072
1073 *pMcBcFilter = pHddCtx->configuredMcastBcastFilter;
1074 if (pHddCtx->cfg_ini->fhostArpOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301075 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301076 /* ARP offload is enabled, do not block bcast packets at RXP
1077 * Will be using Bitmasking to reset the filter. As we have
1078 * disable Broadcast filtering, Anding with the negation
1079 * of Broadcast BIT
1080 */
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301081 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301082 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301083
1084#ifdef WLAN_NS_OFFLOAD
1085 if (pHddCtx->cfg_ini->fhostNSOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301086 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301087 /* NS offload is enabled, do not block mcast packets at RXP
1088 * Will be using Bitmasking to reset the filter. As we have
1089 * disable Multicast filtering, Anding with the negation
1090 * of Multicast BIT
1091 */
1092 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301093 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301094#endif
1095
1096 pHddCtx->configuredMcastBcastFilter = *pMcBcFilter;
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301097}
1098
Jeff Johnson295189b2012-06-20 16:38:30 -07001099void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter)
1100{
1101 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001102 tpSirWlanSetRxpFilters wlanRxpFilterParam =
1103 vos_mem_malloc(sizeof(tSirWlanSetRxpFilters));
1104 if(NULL == wlanRxpFilterParam)
1105 {
1106 hddLog(VOS_TRACE_LEVEL_FATAL,
1107 "%s: vos_mem_alloc failed ", __func__);
1108 return;
1109 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001110 hddLog(VOS_TRACE_LEVEL_INFO,
1111 "%s: Configuring Mcast/Bcast Filter Setting. setfilter %d", __func__, setfilter);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301112 if (TRUE == setfilter)
1113 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301114 hdd_mcbc_filter_modification(pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301115 &wlanRxpFilterParam->configuredMcstBcstFilterSetting);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301116 }
1117 else
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301118 {
1119 /*Use the current configured value to clear*/
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301120 wlanRxpFilterParam->configuredMcstBcstFilterSetting =
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301121 pHddCtx->configuredMcastBcastFilter;
1122 }
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301123
Jeff Johnson295189b2012-06-20 16:38:30 -07001124 wlanRxpFilterParam->setMcstBcstFilter = setfilter;
Jeff Johnson295189b2012-06-20 16:38:30 -07001125 halStatus = sme_ConfigureRxpFilter(pHddCtx->hHal, wlanRxpFilterParam);
Chilam Ngc4244af2013-04-01 15:37:32 -07001126 if (eHAL_STATUS_SUCCESS != halStatus)
1127 vos_mem_free(wlanRxpFilterParam);
Jeff Johnson295189b2012-06-20 16:38:30 -07001128 if(setfilter && (eHAL_STATUS_SUCCESS == halStatus))
1129 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
1130}
1131
Jeff Johnson295189b2012-06-20 16:38:30 -07001132static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx,
1133 hdd_adapter_t *pAdapter)
1134{
1135 eHalStatus halStatus = eHAL_STATUS_FAILURE;
1136 tpSirWlanSuspendParam wlanSuspendParam =
1137 vos_mem_malloc(sizeof(tSirWlanSuspendParam));
1138
Amar Singhald53568e2013-09-26 11:03:45 -07001139 if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid) {
1140 pHddCtx->sus_res_mcastbcast_filter =
1141 pHddCtx->configuredMcastBcastFilter;
1142 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
1143 hddLog(VOS_TRACE_LEVEL_INFO, "offload: hdd_conf_suspend_ind");
1144 hddLog(VOS_TRACE_LEVEL_INFO, "configuredMCastBcastFilter saved = %d",
1145 pHddCtx->configuredMcastBcastFilter);
1146
1147 }
1148
Amar Singhal49fdfd52013-08-13 13:25:12 -07001149
Jeff Johnson295189b2012-06-20 16:38:30 -07001150 if(NULL == wlanSuspendParam)
1151 {
1152 hddLog(VOS_TRACE_LEVEL_FATAL,
1153 "%s: vos_mem_alloc failed ", __func__);
1154 return;
1155 }
1156
Amar Singhald53568e2013-09-26 11:03:45 -07001157 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001158 "%s: send wlan suspend indication", __func__);
1159
1160 if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER))
1161 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301162 //Configure supported OffLoads
1163 hdd_conf_hostoffload(pAdapter, TRUE);
1164 wlanSuspendParam->configuredMcstBcstFilterSetting = pHddCtx->configuredMcastBcastFilter;
Jeff Johnson295189b2012-06-20 16:38:30 -07001165
1166#ifdef WLAN_FEATURE_PACKET_FILTERING
madan mohan koyyalamudibfd9cef2013-07-01 18:39:37 +05301167 /* During suspend, configure MC Addr list filter to the firmware
1168 * function takes care of checking necessary conditions before
1169 * configuring.
1170 */
1171 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001172#endif
1173 }
1174
1175 halStatus = sme_ConfigureSuspendInd(pHddCtx->hHal, wlanSuspendParam);
1176 if(eHAL_STATUS_SUCCESS == halStatus)
1177 {
1178 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
Chilam Ngc4244af2013-04-01 15:37:32 -07001179 } else {
c_hpothuffdb5272013-10-02 16:42:35 +05301180 hddLog(VOS_TRACE_LEVEL_ERROR,
1181 FL("sme_ConfigureSuspendInd returned failure %d"), halStatus);
Chilam Ngc4244af2013-04-01 15:37:32 -07001182 vos_mem_free(wlanSuspendParam);
Jeff Johnson295189b2012-06-20 16:38:30 -07001183 }
1184}
1185
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301186static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001187{
Chilam Ngc4244af2013-04-01 15:37:32 -07001188 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Yathish9f22e662012-12-10 14:21:35 -08001189 hdd_context_t* pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Chilam Ngc4244af2013-04-01 15:37:32 -07001190 tpSirWlanResumeParam wlanResumeParam;
Jeff Johnson295189b2012-06-20 16:38:30 -07001191
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301192 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001193 "%s: send wlan resume indication", __func__);
1194
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301195 wlanResumeParam = vos_mem_malloc(sizeof(tSirWlanResumeParam));
1196
1197 if (NULL == wlanResumeParam)
Jeff Johnson295189b2012-06-20 16:38:30 -07001198 {
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301199 hddLog(VOS_TRACE_LEVEL_FATAL,
1200 "%s: memory allocation failed for wlanResumeParam ", __func__);
1201 return;
Jeff Johnson295189b2012-06-20 16:38:30 -07001202 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001203
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301204 //Disable supported OffLoads
1205 hdd_conf_hostoffload(pAdapter, FALSE);
1206
1207 wlanResumeParam->configuredMcstBcstFilterSetting =
1208 pHddCtx->configuredMcastBcastFilter;
1209 halStatus = sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam);
1210 if (eHAL_STATUS_SUCCESS != halStatus)
1211 {
c_hpothuffdb5272013-10-02 16:42:35 +05301212 hddLog(VOS_TRACE_LEVEL_ERROR,
1213 "%s: sme_ConfigureResumeReq return failure %d", __func__, halStatus);
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301214 vos_mem_free(wlanResumeParam);
1215 }
1216
1217 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
1218
Amar Singhalf8ba2b82013-12-02 12:54:38 -08001219 if (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid) {
1220 pHddCtx->configuredMcastBcastFilter =
1221 pHddCtx->sus_res_mcastbcast_filter;
1222 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_FALSE;
1223 }
Amar Singhald53568e2013-09-26 11:03:45 -07001224
1225 hddLog(VOS_TRACE_LEVEL_INFO,
1226 "offload: in hdd_conf_resume_ind, restoring configuredMcastBcastFilter");
1227 hddLog(VOS_TRACE_LEVEL_INFO, "configuredMcastBcastFilter = %d",
1228 pHddCtx->configuredMcastBcastFilter);
Amar Singhal49fdfd52013-08-13 13:25:12 -07001229
Chilam Ngc4244af2013-04-01 15:37:32 -07001230
madan mohan koyyalamudibfd9cef2013-07-01 18:39:37 +05301231#ifdef WLAN_FEATURE_PACKET_FILTERING
1232 /* Filer was applied during suspend inditication
1233 * clear it when we resume.
1234 */
1235 wlan_hdd_set_mc_addr_list(pAdapter, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001236#endif
1237}
Jeff Johnson295189b2012-06-20 16:38:30 -07001238
Jeff Johnson295189b2012-06-20 16:38:30 -07001239//Suspend routine registered with Android OS
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001240void hdd_suspend_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001241{
1242 hdd_context_t *pHddCtx = NULL;
1243 v_CONTEXT_t pVosContext = NULL;
1244
Jeff Johnson295189b2012-06-20 16:38:30 -07001245 VOS_STATUS status;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301246 hdd_adapter_t *pAdapter = NULL;
1247 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301248 bool hdd_enter_bmps = FALSE;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001249
Jeff Johnson295189b2012-06-20 16:38:30 -07001250 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__);
1251
1252 //Get the global VOSS context.
1253 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1254 if(!pVosContext) {
1255 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1256 return;
1257 }
1258
1259 //Get the HDD context.
1260 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1261
1262 if(!pHddCtx) {
1263 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1264 return;
1265 }
1266
1267 if (pHddCtx->isLogpInProgress) {
1268 hddLog(VOS_TRACE_LEVEL_ERROR,
1269 "%s: Ignore suspend wlan, LOGP in progress!", __func__);
1270 return;
1271 }
1272
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301273 hdd_set_pwrparams(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001274 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1275 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1276 {
1277 pAdapter = pAdapterNode->pAdapter;
1278 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001279 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001280 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
1281
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001282 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001283 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1284 pAdapterNode = pNext;
1285 continue;
1286 }
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301287 /* Avoid multiple enter/exit BMPS in this while loop using
1288 * hdd_enter_bmps flag
1289 */
1290 if (FALSE == hdd_enter_bmps && (BMPS == pmcGetPmcState(pHddCtx->hHal)))
1291 {
1292 hdd_enter_bmps = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001293
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301294 /* If device was already in BMPS, and dynamic DTIM is set,
1295 * exit(set the device to full power) and enter BMPS again
1296 * to reflect new DTIM value */
1297 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
1298
1299 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
1300
1301 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1302 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001303#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1304 if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1305 {
1306 //stop the interface before putting the chip to standby
1307 netif_tx_disable(pAdapter->dev);
1308 netif_carrier_off(pAdapter->dev);
1309 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301310 else if (pHddCtx->cfg_ini->nEnableSuspend ==
Jeff Johnson295189b2012-06-20 16:38:30 -07001311 WLAN_MAP_SUSPEND_TO_DEEP_SLEEP)
1312 {
1313 //Execute deep sleep procedure
1314 hdd_enter_deep_sleep(pHddCtx, pAdapter);
1315 }
1316#endif
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301317
1318 /*Suspend notification sent down to driver*/
1319 hdd_conf_suspend_ind(pHddCtx, pAdapter);
1320
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301321 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1322 pAdapterNode = pNext;
1323 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301324 pHddCtx->hdd_wlan_suspended = TRUE;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301325
Jeff Johnson295189b2012-06-20 16:38:30 -07001326#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1327 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1328 {
1329 hdd_enter_standby(pHddCtx);
1330 }
1331#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001332
1333 return;
1334}
1335
1336static void hdd_PowerStateChangedCB
1337(
1338 v_PVOID_t callbackContext,
1339 tPmcState newState
1340)
1341{
1342 hdd_context_t *pHddCtx = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07001343 /* if the driver was not in BMPS during early suspend,
1344 * the dynamic DTIM is now updated at Riva */
1345 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended
1346 && pHddCtx->cfg_ini->enableDynamicDTIM
1347 && (pHddCtx->hdd_ignore_dtim_enabled == FALSE))
1348 {
1349 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1350 }
1351 spin_lock(&pHddCtx->filter_lock);
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301352 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended)
1353 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001354 spin_unlock(&pHddCtx->filter_lock);
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301355 if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid)
1356 {
Amar Singhald53568e2013-09-26 11:03:45 -07001357 pHddCtx->sus_res_mcastbcast_filter =
1358 pHddCtx->configuredMcastBcastFilter;
1359 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
1360
1361 hddLog(VOS_TRACE_LEVEL_INFO, "offload: callback to associated");
1362 hddLog(VOS_TRACE_LEVEL_INFO, "saving configuredMcastBcastFilter = %d",
1363 pHddCtx->configuredMcastBcastFilter);
1364 hddLog(VOS_TRACE_LEVEL_INFO,
1365 "offload: calling hdd_conf_mcastbcast_filter");
1366
1367 }
1368
Jeff Johnson295189b2012-06-20 16:38:30 -07001369 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001370 if(pHddCtx->hdd_mcastbcast_filter_set != TRUE)
1371 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__);
1372 }
Amar Singhal49fdfd52013-08-13 13:25:12 -07001373 else
Mihir Shete793209f2014-01-06 11:01:12 +05301374 {
1375 /* Android framework can send resume request when the WCN chip is
1376 * in IMPS mode. When the chip exits IMPS mode the firmware will
1377 * restore all the registers to the state they were before the chip
1378 * entered IMPS and so our hardware filter settings confgured by the
1379 * resume request will be lost. So reconfigure the filters on detecting
1380 * a change in the power state of the WCN chip.
1381 */
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301382 spin_unlock(&pHddCtx->filter_lock);
Mihir Shete793209f2014-01-06 11:01:12 +05301383 if (IMPS != newState)
1384 {
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301385 spin_lock(&pHddCtx->filter_lock);
Mihir Shete793209f2014-01-06 11:01:12 +05301386 if (FALSE == pHddCtx->hdd_wlan_suspended)
1387 {
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301388 spin_unlock(&pHddCtx->filter_lock);
Mihir Shete793209f2014-01-06 11:01:12 +05301389 hddLog(VOS_TRACE_LEVEL_INFO,
1390 "Not in IMPS/BMPS and suspended state");
1391 hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
1392 }
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301393 else
1394 {
1395 spin_unlock(&pHddCtx->filter_lock);
1396 }
Mihir Shete793209f2014-01-06 11:01:12 +05301397 }
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301398 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001399}
1400
1401
1402
1403void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx)
1404{
1405 v_CONTEXT_t pVosContext;
1406 tHalHandle smeContext;
1407
1408 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1409 if (NULL == pVosContext)
1410 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001411 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001412 return;
1413 }
1414 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1415 if (NULL == smeContext)
1416 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001417 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001418 return;
1419 }
1420
1421 spin_lock_init(&pHddCtx->filter_lock);
1422 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1423 pHddCtx->cfg_ini->nEnableSuspend)
1424 {
1425 pmcRegisterDeviceStateUpdateInd(smeContext,
1426 hdd_PowerStateChangedCB, pHddCtx);
1427 }
1428}
1429
1430void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx)
1431{
1432 v_CONTEXT_t pVosContext;
1433 tHalHandle smeContext;
1434
1435 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1436 if (NULL == pVosContext)
1437 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001438 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001439 return;
1440 }
1441 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1442 if (NULL == smeContext)
1443 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001444 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001445 return;
1446 }
1447
1448 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1449 pHddCtx->cfg_ini->nEnableSuspend)
1450 {
1451 pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB);
1452 }
1453}
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301454
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301455#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301456void hdd_conf_gtk_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301457{
1458 eHalStatus ret;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301459 tSirGtkOffloadParams hddGtkOffloadReqParams;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301460 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1461
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301462 if(fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301463 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301464 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1465 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags ))
1466 {
1467 vos_mem_copy(&hddGtkOffloadReqParams,
1468 &pHddStaCtx->gtkOffloadReqParams,
1469 sizeof (tSirGtkOffloadParams));
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301470
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301471 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1472 &hddGtkOffloadReqParams, pAdapter->sessionId);
1473 if (eHAL_STATUS_SUCCESS != ret)
1474 {
1475 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1476 "%s: sme_SetGTKOffload failed, returned %d",
1477 __func__, ret);
1478 return;
1479 }
1480
1481 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1482 "%s: sme_SetGTKOffload successfull", __func__);
1483 }
1484
1485 }
1486 else
1487 {
1488 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1489 (0 == memcmp(&pHddStaCtx->gtkOffloadReqParams.bssId,
1490 &pHddStaCtx->conn_info.bssId, WNI_CFG_BSSID_LEN)) &&
1491 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags))
1492 {
1493
1494 /* Host driver has previously offloaded GTK rekey */
1495 ret = sme_GetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301496 wlan_hdd_cfg80211_update_replayCounterCallback,
1497 pAdapter, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301498 if (eHAL_STATUS_SUCCESS != ret)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301499
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301500 {
1501 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1502 "%s: sme_GetGTKOffload failed, returned %d",
1503 __func__, ret);
1504 return;
1505 }
1506 else
1507 {
1508 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1509 "%s: sme_GetGTKOffload successful",
1510 __func__);
1511
1512 /* Sending GTK offload dissable */
1513 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
1514 sizeof (tSirGtkOffloadParams));
1515 hddGtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE;
1516 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301517 &hddGtkOffloadReqParams, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301518 if (eHAL_STATUS_SUCCESS != ret)
1519 {
1520 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1521 "%s: failed to dissable GTK offload, returned %d",
1522 __func__, ret);
1523 return;
1524 }
1525 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1526 "%s: successfully dissabled GTK offload request to HAL",
1527 __func__);
1528 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301529 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301530 }
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301531 return;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301532}
1533#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
Jeff Johnson295189b2012-06-20 16:38:30 -07001534
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001535void hdd_resume_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001536{
1537 hdd_context_t *pHddCtx = NULL;
1538 hdd_adapter_t *pAdapter = NULL;
1539 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1540 VOS_STATUS status;
1541 v_CONTEXT_t pVosContext = NULL;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001542
Jeff Johnson295189b2012-06-20 16:38:30 -07001543 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
1544
1545 //Get the global VOSS context.
1546 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1547 if(!pVosContext) {
1548 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1549 return;
1550 }
1551
1552 //Get the HDD context.
1553 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1554
1555 if(!pHddCtx) {
1556 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1557 return;
1558 }
1559
1560 if (pHddCtx->isLogpInProgress) {
1561 hddLog(VOS_TRACE_LEVEL_INFO,
1562 "%s: Ignore resume wlan, LOGP in progress!", __func__);
1563 return;
1564 }
1565
Jeff Johnson295189b2012-06-20 16:38:30 -07001566 pHddCtx->hdd_wlan_suspended = FALSE;
1567 /*loop through all adapters. Concurrency */
1568 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1569
1570 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1571 {
1572 pAdapter = pAdapterNode->pAdapter;
1573 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001574 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001575 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001576 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001577 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1578 pAdapterNode = pNext;
1579 continue;
1580 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301581
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301582
Jeff Johnson295189b2012-06-20 16:38:30 -07001583#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1584 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP)
1585 {
1586 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__);
1587 hdd_exit_deep_sleep(pAdapter);
1588 }
1589#endif
1590
1591 if(pHddCtx->hdd_ignore_dtim_enabled == TRUE)
1592 {
1593 /*Switch back to DTIM 1*/
1594 tSirSetPowerParamsReq powerRequest = { 0 };
1595
1596 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
1597 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07001598 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001599
1600 /*Disabled ModulatedDTIM if enabled on suspend*/
1601 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1602 powerRequest.uDTIMPeriod = 0;
1603
1604 /* Update ignoreDTIM and ListedInterval in CFG with default values */
1605 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1606 NULL, eANI_BOOLEAN_FALSE);
1607 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1608 NULL, eANI_BOOLEAN_FALSE);
1609
1610 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001611 "Switch to DTIM%d",powerRequest.uListenInterval);
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08001612 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001613
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301614 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
1615 {
1616 /* put the device into full power */
1617 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001618
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301619 /* put the device back into BMPS */
1620 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
Jeff Johnson295189b2012-06-20 16:38:30 -07001621
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301622 pHddCtx->hdd_ignore_dtim_enabled = FALSE;
1623 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001624 }
1625
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301626 hdd_conf_resume_ind(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001627 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1628 pAdapterNode = pNext;
1629 }
1630
1631#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1632 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY)
1633 {
1634 hdd_exit_standby(pHddCtx);
1635 }
1636#endif
1637
Jeff Johnson295189b2012-06-20 16:38:30 -07001638 return;
1639}
1640
Jeff Johnson295189b2012-06-20 16:38:30 -07001641VOS_STATUS hdd_wlan_reset_initialization(void)
1642{
Jeff Johnson295189b2012-06-20 16:38:30 -07001643 v_CONTEXT_t pVosContext = NULL;
1644
1645 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1646
1647 //Get the global VOSS context.
1648 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1649 if(!pVosContext)
1650 {
1651 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1652 return VOS_STATUS_E_FAILURE;
1653 }
1654
1655 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__);
1656
1657 // Prevent the phone from going to sleep
1658 hdd_prevent_suspend();
1659
Jeff Johnson295189b2012-06-20 16:38:30 -07001660 return VOS_STATUS_SUCCESS;
1661}
1662
1663
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001664/*
1665 * Based on the ioctl command recieved by HDD, put WLAN driver
1666 * into the quiet mode. This is the same as the early suspend
1667 * notification that driver used to listen
1668 */
1669void hdd_set_wlan_suspend_mode(bool suspend)
Jeff Johnson295189b2012-06-20 16:38:30 -07001670{
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001671 if (suspend)
1672 hdd_suspend_wlan();
1673 else
1674 hdd_resume_wlan();
Jeff Johnson295189b2012-06-20 16:38:30 -07001675}
1676
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001677static void hdd_ssr_timer_init(void)
1678{
1679 init_timer(&ssr_timer);
1680}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001681
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001682static void hdd_ssr_timer_del(void)
1683{
1684 del_timer(&ssr_timer);
1685 ssr_timer_started = false;
1686}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001687
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001688static void hdd_ssr_timer_cb(unsigned long data)
1689{
1690 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD SSR timer expired", __func__);
Sameer Thalappile5637f42013-08-07 15:46:55 -07001691
1692#ifdef WCN_PRONTO
1693 if (wcnss_hardware_type() == WCNSS_PRONTO_HW)
1694 wcnss_pronto_log_debug_regs();
1695#endif
1696
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001697 VOS_BUG(0);
1698}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001699
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001700static void hdd_ssr_timer_start(int msec)
1701{
1702 if(ssr_timer_started)
1703 {
1704 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: trying to start SSR timer when it's running"
1705 ,__func__);
1706 }
1707 ssr_timer.expires = jiffies + msecs_to_jiffies(msec);
1708 ssr_timer.function = hdd_ssr_timer_cb;
1709 add_timer(&ssr_timer);
1710 ssr_timer_started = true;
1711}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001712
Jeff Johnson295189b2012-06-20 16:38:30 -07001713/* the HDD interface to WLAN driver shutdown,
1714 * the primary shutdown function in SSR
1715 */
1716VOS_STATUS hdd_wlan_shutdown(void)
1717{
1718 VOS_STATUS vosStatus;
1719 v_CONTEXT_t pVosContext = NULL;
1720 hdd_context_t *pHddCtx = NULL;
1721 pVosSchedContext vosSchedContext = NULL;
c_hpothuffdb5272013-10-02 16:42:35 +05301722 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07001723
1724 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__);
1725
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001726 /* if re-init never happens, then do SSR1 */
1727 hdd_ssr_timer_init();
1728 hdd_ssr_timer_start(HDD_SSR_BRING_UP_TIME);
1729
Jeff Johnson295189b2012-06-20 16:38:30 -07001730 /* Get the global VOSS context. */
1731 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1732 if(!pVosContext) {
1733 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1734 return VOS_STATUS_E_FAILURE;
1735 }
1736 /* Get the HDD context. */
1737 pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1738 if(!pHddCtx) {
1739 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1740 return VOS_STATUS_E_FAILURE;
1741 }
c_hpothud662a352013-12-26 15:09:12 +05301742
1743 //Stop the traffic monitor timer
1744 if ( VOS_TIMER_STATE_RUNNING ==
1745 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
1746 {
1747 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
1748 }
1749
Jeff Johnson295189b2012-06-20 16:38:30 -07001750 hdd_reset_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001751 /* DeRegister with platform driver as client for Suspend/Resume */
1752 vosStatus = hddDeregisterPmOps(pHddCtx);
1753 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1754 {
1755 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
1756 }
1757
1758 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
1759 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1760 {
1761 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
1762 }
1763
1764 /* Disable IMPS/BMPS as we do not want the device to enter any power
1765 * save mode on its own during reset sequence
1766 */
1767 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1768 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1769 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1770
1771 vosSchedContext = get_vos_sched_ctxt();
1772
1773 /* Wakeup all driver threads */
1774 if(TRUE == pHddCtx->isMcThreadSuspended){
1775 complete(&vosSchedContext->ResumeMcEvent);
1776 pHddCtx->isMcThreadSuspended= FALSE;
1777 }
1778 if(TRUE == pHddCtx->isTxThreadSuspended){
1779 complete(&vosSchedContext->ResumeTxEvent);
1780 pHddCtx->isTxThreadSuspended= FALSE;
1781 }
1782 if(TRUE == pHddCtx->isRxThreadSuspended){
1783 complete(&vosSchedContext->ResumeRxEvent);
1784 pHddCtx->isRxThreadSuspended= FALSE;
1785 }
1786 /* Reset the Suspend Variable */
1787 pHddCtx->isWlanSuspended = FALSE;
1788
1789 /* Stop all the threads; we do not want any messages to be a processed,
1790 * any more and the best way to ensure that is to terminate the threads
1791 * gracefully.
1792 */
1793 /* Wait for MC to exit */
1794 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
1795 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
1796 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
1797 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
c_hpothuffdb5272013-10-02 16:42:35 +05301798 ret = wait_for_completion_interruptible(&vosSchedContext->McShutdown);
1799 if (0 >= ret)
1800 {
1801 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:wait on McShutdown failed %ld",
1802 __func__, ret);
1803 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001804
1805 /* Wait for TX to exit */
1806 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
1807 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
1808 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
1809 wake_up_interruptible(&vosSchedContext->txWaitQueue);
c_hpothuffdb5272013-10-02 16:42:35 +05301810 ret = wait_for_completion_interruptible(&vosSchedContext->TxShutdown);
1811 if (0 >= ret)
1812 {
1813 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:wait on TxShutdown failed %ld",
1814 __func__, ret);
1815 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001816
1817 /* Wait for RX to exit */
1818 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
1819 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
1820 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
1821 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
c_hpothuffdb5272013-10-02 16:42:35 +05301822
1823 ret = wait_for_completion_interruptible(&vosSchedContext->RxShutdown);
1824 if (0 >= ret)
1825 {
1826 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:wait on RxShutdown failed %ld",
1827 __func__, ret);
1828 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001829
1830#ifdef WLAN_BTAMP_FEATURE
1831 vosStatus = WLANBAP_Stop(pVosContext);
1832 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1833 {
1834 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1835 "%s: Failed to stop BAP",__func__);
1836 }
1837#endif //WLAN_BTAMP_FEATURE
1838 vosStatus = vos_wda_shutdown(pVosContext);
c_hpothuffdb5272013-10-02 16:42:35 +05301839 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1840 {
1841 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1842 "%s: Failed to stop wda %d", __func__, vosStatus);
1843 VOS_ASSERT(0);
1844 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001845
1846 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
1847 /* Stop SME - Cannot invoke vos_stop as vos_stop relies
1848 * on threads being running to process the SYS Stop
1849 */
Kiet Lama72a2322013-11-15 11:18:11 +05301850 vosStatus = sme_Stop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
c_hpothuffdb5272013-10-02 16:42:35 +05301851 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1852 {
1853 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1854 "%s: Failed to stop sme %d", __func__, vosStatus);
1855 VOS_ASSERT(0);
1856 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001857
1858 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
1859 /* Stop MAC (PE and HAL) */
1860 vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
c_hpothuffdb5272013-10-02 16:42:35 +05301861 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1862 {
1863 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1864 "%s: Failed to stop mac %d", __func__, vosStatus);
1865 VOS_ASSERT(0);
1866 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001867
1868 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
1869 /* Stop TL */
1870 vosStatus = WLANTL_Stop(pVosContext);
c_hpothuffdb5272013-10-02 16:42:35 +05301871 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1872 {
1873 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1874 "%s: Failed to stop TL %d", __func__, vosStatus);
1875 VOS_ASSERT(0);
1876 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001877
Jeff Johnson295189b2012-06-20 16:38:30 -07001878 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001879 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__);
1880 /* Clean up message queues of TX and MC thread */
1881 vos_sched_flush_mc_mqs(vosSchedContext);
1882 vos_sched_flush_tx_mqs(vosSchedContext);
1883 vos_sched_flush_rx_mqs(vosSchedContext);
1884
1885 /* Deinit all the TX and MC queues */
1886 vos_sched_deinit_mqs(vosSchedContext);
1887 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__);
1888
1889 /* shutdown VOSS */
1890 vos_shutdown(pVosContext);
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05301891
1892 /*mac context has already been released in mac_close call
1893 so setting it to NULL in hdd context*/
1894 pHddCtx->hHal = (tHalHandle)NULL;
1895
Jeff Johnson295189b2012-06-20 16:38:30 -07001896 if (free_riva_power_on_lock("wlan"))
1897 {
1898 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
1899 __func__);
1900 }
1901 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete"
1902 ,__func__);
1903 return VOS_STATUS_SUCCESS;
1904}
1905
1906
1907
1908/* the HDD interface to WLAN driver re-init.
1909 * This is called to initialize/start WLAN driver after a shutdown.
1910 */
1911VOS_STATUS hdd_wlan_re_init(void)
1912{
1913 VOS_STATUS vosStatus;
1914 v_CONTEXT_t pVosContext = NULL;
1915 hdd_context_t *pHddCtx = NULL;
1916 eHalStatus halStatus;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07001917#ifdef HAVE_WCNSS_CAL_DOWNLOAD
1918 int max_retries = 0;
1919#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001920#ifdef WLAN_BTAMP_FEATURE
1921 hdd_config_t *pConfig = NULL;
1922 WLANBAP_ConfigType btAmpConfig;
1923#endif
1924
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001925 hdd_ssr_timer_del();
Jeff Johnson295189b2012-06-20 16:38:30 -07001926 hdd_prevent_suspend();
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001927
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07001928#ifdef HAVE_WCNSS_CAL_DOWNLOAD
1929 /* wait until WCNSS driver downloads NV */
1930 while (!wcnss_device_ready() && 5 >= ++max_retries) {
1931 msleep(1000);
1932 }
1933 if (max_retries >= 5) {
1934 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
1935 goto err_re_init;
1936 }
1937#endif
1938
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07001939 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, TRUE);
1940
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001941 /* The driver should always be initialized in STA mode after SSR */
1942 hdd_set_conparam(0);
1943
Jeff Johnson295189b2012-06-20 16:38:30 -07001944 /* Re-open VOSS, it is a re-open b'se control transport was never closed. */
1945 vosStatus = vos_open(&pVosContext, 0);
1946 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1947 {
1948 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
1949 goto err_re_init;
1950 }
1951
1952 /* Get the HDD context. */
1953 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1954 if(!pHddCtx)
1955 {
1956 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1957 goto err_vosclose;
1958 }
1959
1960 /* Save the hal context in Adapter */
1961 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
1962 if ( NULL == pHddCtx->hHal )
1963 {
1964 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
1965 goto err_vosclose;
1966 }
1967
1968 /* Set the SME configuration parameters. */
1969 vosStatus = hdd_set_sme_config(pHddCtx);
1970 if ( VOS_STATUS_SUCCESS != vosStatus )
1971 {
1972 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
1973 goto err_vosclose;
1974 }
1975
1976 /* Initialize the WMM module */
1977 vosStatus = hdd_wmm_init(pHddCtx);
1978 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
1979 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001980 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001981 goto err_vosclose;
1982 }
1983
1984 vosStatus = vos_preStart( pHddCtx->pvosContext );
1985 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1986 {
1987 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
1988 goto err_vosclose;
1989 }
1990
1991 /* In the integrated architecture we update the configuration from
1992 the INI file and from NV before vOSS has been started so that
1993 the final contents are available to send down to the cCPU */
1994 /* Apply the cfg.ini to cfg.dat */
1995 if (FALSE == hdd_update_config_dat(pHddCtx))
1996 {
1997 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
1998 goto err_vosclose;
1999 }
2000
2001 /* Set the MAC Address, currently this is used by HAL to add self sta.
2002 * Remove this once self sta is added as part of session open. */
2003 halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID,
2004 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
2005 sizeof(pHddCtx->cfg_ini->intfMacAddr[0]));
2006 if (!HAL_STATUS_SUCCESS(halStatus))
2007 {
2008 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
2009 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus);
2010 goto err_vosclose;
2011 }
2012
2013 /* Start VOSS which starts up the SME/MAC/HAL modules and everything else
2014 Note: Firmware image will be read and downloaded inside vos_start API */
2015 vosStatus = vos_start( pVosContext );
2016 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2017 {
2018 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
2019 goto err_vosclose;
2020 }
2021
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07002022 /* Exchange capability info between Host and FW and also get versioning info from FW */
2023 hdd_exchange_version_and_caps(pHddCtx);
2024
Jeff Johnson295189b2012-06-20 16:38:30 -07002025 vosStatus = hdd_post_voss_start_config( pHddCtx );
2026 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2027 {
2028 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
2029 __func__);
2030 goto err_vosstop;
2031 }
2032
2033#ifdef WLAN_BTAMP_FEATURE
2034 vosStatus = WLANBAP_Open(pVosContext);
2035 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
2036 {
2037 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2038 "%s: Failed to open BAP",__func__);
2039 goto err_vosstop;
2040 }
2041 vosStatus = BSL_Init(pVosContext);
2042 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
2043 {
2044 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2045 "%s: Failed to Init BSL",__func__);
2046 goto err_bap_close;
2047 }
2048 vosStatus = WLANBAP_Start(pVosContext);
2049 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2050 {
2051 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2052 "%s: Failed to start TL",__func__);
2053 goto err_bap_close;
2054 }
2055 pConfig = pHddCtx->cfg_ini;
2056 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
2057 vosStatus = WLANBAP_SetConfig(&btAmpConfig);
2058#endif //WLAN_BTAMP_FEATURE
2059
2060 /* Restart all adapters */
2061 hdd_start_all_adapters(pHddCtx);
2062 pHddCtx->isLogpInProgress = FALSE;
Sameer Thalappilb511beb2013-09-09 17:11:51 -07002063 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07002064 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002065 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002066
2067 /* Register with platform driver as client for Suspend/Resume */
2068 vosStatus = hddRegisterPmOps(pHddCtx);
2069 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2070 {
2071 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
2072 goto err_bap_stop;
2073 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002074 /* Allow the phone to go to sleep */
2075 hdd_allow_suspend();
2076 /* register for riva power on lock */
2077 if (req_riva_power_on_lock("wlan"))
2078 {
2079 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
2080 __func__);
2081 goto err_unregister_pmops;
2082 }
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07002083 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07002084 goto success;
2085
2086err_unregister_pmops:
2087 hddDeregisterPmOps(pHddCtx);
2088
2089err_bap_stop:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002090#ifdef CONFIG_HAS_EARLYSUSPEND
2091 hdd_unregister_mcast_bcast_filter(pHddCtx);
2092#endif
2093 hdd_close_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002094#ifdef WLAN_BTAMP_FEATURE
Jeff Johnson32d95a32012-09-10 13:15:23 -07002095 WLANBAP_Stop(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07002096#endif
2097
2098#ifdef WLAN_BTAMP_FEATURE
2099err_bap_close:
2100 WLANBAP_Close(pVosContext);
2101#endif
2102
2103err_vosstop:
2104 vos_stop(pVosContext);
2105
2106err_vosclose:
2107 vos_close(pVosContext);
2108 vos_sched_close(pVosContext);
2109 if (pHddCtx)
2110 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002111 /* Unregister the Net Device Notifier */
2112 unregister_netdevice_notifier(&hdd_netdev_notifier);
2113 /* Clean up HDD Nlink Service */
2114 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07002115#ifdef WLAN_KD_READY_NOTIFIER
2116 nl_srv_exit(pHddCtx->ptt_pid);
2117#else
Jeff Johnson295189b2012-06-20 16:38:30 -07002118 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07002119#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07002120 /* Free up dynamically allocated members inside HDD Adapter */
2121 kfree(pHddCtx->cfg_ini);
2122 pHddCtx->cfg_ini= NULL;
2123
Jeff Johnson295189b2012-06-20 16:38:30 -07002124 wiphy_unregister(pHddCtx->wiphy);
2125 wiphy_free(pHddCtx->wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07002126 }
2127 vos_preClose(&pVosContext);
2128
2129#ifdef MEMORY_DEBUG
2130 vos_mem_exit();
2131#endif
2132
2133err_re_init:
2134 /* Allow the phone to go to sleep */
2135 hdd_allow_suspend();
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07002136 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07002137 VOS_BUG(0);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002138 return -EPERM;
Jeff Johnson295189b2012-06-20 16:38:30 -07002139
2140success:
2141 /* Trigger replay of BTC events */
2142 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
2143 return VOS_STATUS_SUCCESS;
2144}