blob: 9550b8bb0b4eccc6a6b524319940bc48f82c0cdd [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 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05301014 hddLog(VOS_TRACE_LEVEL_ERROR, FL("IP Address is not assigned"));
1015 return VOS_STATUS_E_AGAIN;
Jeff Johnson295189b2012-06-20 16:38:30 -07001016 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301017
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05301018 if (fenable == 1 && !pAdapter->ipv4_notifier_registered)
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301019 {
1020 // Register IPv4 notifier to notify if any change in IP
1021 // So that we can reconfigure the offload parameters
1022 pAdapter->ipv4_notifier.notifier_call =
1023 wlan_hdd_ipv4_changed;
1024 ret = register_inetaddr_notifier(&pAdapter->ipv4_notifier);
1025 if (ret)
1026 {
1027 hddLog(LOGE, FL("Failed to register IPv4 notifier"));
1028 }
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05301029 else
1030 {
1031 hddLog(LOG1, FL("Registered IPv4 notifier"));
1032 pAdapter->ipv4_notifier_registered = true;
1033 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301034 }
1035 return VOS_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07001036 }
1037 else
1038 {
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05301039 if (pAdapter->ipv4_notifier_registered)
1040 {
1041 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
1042 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
1043 pAdapter->ipv4_notifier_registered = false;
1044 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001045 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
1046 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
1047 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
1048
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301049 if (eHAL_STATUS_SUCCESS !=
1050 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1051 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -07001052 {
1053 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to disable host "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001054 "offload feature", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001055 return VOS_STATUS_E_FAILURE;
1056 }
1057 return VOS_STATUS_SUCCESS;
1058 }
1059}
1060
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301061/*
1062 * This function is called before setting mcbc filters
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301063 * to modify filter value considering Different Offloads
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301064*/
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301065void hdd_mcbc_filter_modification(hdd_context_t* pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301066 tANI_U8 *pMcBcFilter)
1067{
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301068 if (NULL == pHddCtx)
1069 {
1070 hddLog(VOS_TRACE_LEVEL_ERROR, FL("NULL HDD context passed"));
1071 return;
1072 }
1073
1074 *pMcBcFilter = pHddCtx->configuredMcastBcastFilter;
1075 if (pHddCtx->cfg_ini->fhostArpOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301076 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301077 /* ARP offload is enabled, do not block bcast packets at RXP
1078 * Will be using Bitmasking to reset the filter. As we have
1079 * disable Broadcast filtering, Anding with the negation
1080 * of Broadcast BIT
1081 */
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301082 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301083 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301084
1085#ifdef WLAN_NS_OFFLOAD
1086 if (pHddCtx->cfg_ini->fhostNSOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301087 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301088 /* NS offload is enabled, do not block mcast packets at RXP
1089 * Will be using Bitmasking to reset the filter. As we have
1090 * disable Multicast filtering, Anding with the negation
1091 * of Multicast BIT
1092 */
1093 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301094 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301095#endif
1096
1097 pHddCtx->configuredMcastBcastFilter = *pMcBcFilter;
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301098}
1099
Jeff Johnson295189b2012-06-20 16:38:30 -07001100void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter)
1101{
1102 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001103 tpSirWlanSetRxpFilters wlanRxpFilterParam =
1104 vos_mem_malloc(sizeof(tSirWlanSetRxpFilters));
1105 if(NULL == wlanRxpFilterParam)
1106 {
1107 hddLog(VOS_TRACE_LEVEL_FATAL,
1108 "%s: vos_mem_alloc failed ", __func__);
1109 return;
1110 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001111 hddLog(VOS_TRACE_LEVEL_INFO,
1112 "%s: Configuring Mcast/Bcast Filter Setting. setfilter %d", __func__, setfilter);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301113 if (TRUE == setfilter)
1114 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301115 hdd_mcbc_filter_modification(pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301116 &wlanRxpFilterParam->configuredMcstBcstFilterSetting);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301117 }
1118 else
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301119 {
1120 /*Use the current configured value to clear*/
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301121 wlanRxpFilterParam->configuredMcstBcstFilterSetting =
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301122 pHddCtx->configuredMcastBcastFilter;
1123 }
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301124
Jeff Johnson295189b2012-06-20 16:38:30 -07001125 wlanRxpFilterParam->setMcstBcstFilter = setfilter;
Jeff Johnson295189b2012-06-20 16:38:30 -07001126 halStatus = sme_ConfigureRxpFilter(pHddCtx->hHal, wlanRxpFilterParam);
Chilam Ngc4244af2013-04-01 15:37:32 -07001127 if (eHAL_STATUS_SUCCESS != halStatus)
1128 vos_mem_free(wlanRxpFilterParam);
Jeff Johnson295189b2012-06-20 16:38:30 -07001129 if(setfilter && (eHAL_STATUS_SUCCESS == halStatus))
1130 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
1131}
1132
Jeff Johnson295189b2012-06-20 16:38:30 -07001133static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx,
1134 hdd_adapter_t *pAdapter)
1135{
1136 eHalStatus halStatus = eHAL_STATUS_FAILURE;
1137 tpSirWlanSuspendParam wlanSuspendParam =
1138 vos_mem_malloc(sizeof(tSirWlanSuspendParam));
1139
Amar Singhald53568e2013-09-26 11:03:45 -07001140 if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid) {
1141 pHddCtx->sus_res_mcastbcast_filter =
1142 pHddCtx->configuredMcastBcastFilter;
1143 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
1144 hddLog(VOS_TRACE_LEVEL_INFO, "offload: hdd_conf_suspend_ind");
1145 hddLog(VOS_TRACE_LEVEL_INFO, "configuredMCastBcastFilter saved = %d",
1146 pHddCtx->configuredMcastBcastFilter);
1147
1148 }
1149
Amar Singhal49fdfd52013-08-13 13:25:12 -07001150
Jeff Johnson295189b2012-06-20 16:38:30 -07001151 if(NULL == wlanSuspendParam)
1152 {
1153 hddLog(VOS_TRACE_LEVEL_FATAL,
1154 "%s: vos_mem_alloc failed ", __func__);
1155 return;
1156 }
1157
Amar Singhald53568e2013-09-26 11:03:45 -07001158 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001159 "%s: send wlan suspend indication", __func__);
1160
1161 if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER))
1162 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301163 //Configure supported OffLoads
1164 hdd_conf_hostoffload(pAdapter, TRUE);
1165 wlanSuspendParam->configuredMcstBcstFilterSetting = pHddCtx->configuredMcastBcastFilter;
Jeff Johnson295189b2012-06-20 16:38:30 -07001166
1167#ifdef WLAN_FEATURE_PACKET_FILTERING
madan mohan koyyalamudibfd9cef2013-07-01 18:39:37 +05301168 /* During suspend, configure MC Addr list filter to the firmware
1169 * function takes care of checking necessary conditions before
1170 * configuring.
1171 */
1172 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001173#endif
1174 }
1175
1176 halStatus = sme_ConfigureSuspendInd(pHddCtx->hHal, wlanSuspendParam);
1177 if(eHAL_STATUS_SUCCESS == halStatus)
1178 {
1179 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
Chilam Ngc4244af2013-04-01 15:37:32 -07001180 } else {
c_hpothuffdb5272013-10-02 16:42:35 +05301181 hddLog(VOS_TRACE_LEVEL_ERROR,
1182 FL("sme_ConfigureSuspendInd returned failure %d"), halStatus);
Chilam Ngc4244af2013-04-01 15:37:32 -07001183 vos_mem_free(wlanSuspendParam);
Jeff Johnson295189b2012-06-20 16:38:30 -07001184 }
1185}
1186
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301187static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001188{
Chilam Ngc4244af2013-04-01 15:37:32 -07001189 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Yathish9f22e662012-12-10 14:21:35 -08001190 hdd_context_t* pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Chilam Ngc4244af2013-04-01 15:37:32 -07001191 tpSirWlanResumeParam wlanResumeParam;
Jeff Johnson295189b2012-06-20 16:38:30 -07001192
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301193 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001194 "%s: send wlan resume indication", __func__);
1195
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301196 wlanResumeParam = vos_mem_malloc(sizeof(tSirWlanResumeParam));
1197
1198 if (NULL == wlanResumeParam)
Jeff Johnson295189b2012-06-20 16:38:30 -07001199 {
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301200 hddLog(VOS_TRACE_LEVEL_FATAL,
1201 "%s: memory allocation failed for wlanResumeParam ", __func__);
1202 return;
Jeff Johnson295189b2012-06-20 16:38:30 -07001203 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001204
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301205 //Disable supported OffLoads
1206 hdd_conf_hostoffload(pAdapter, FALSE);
1207
1208 wlanResumeParam->configuredMcstBcstFilterSetting =
1209 pHddCtx->configuredMcastBcastFilter;
1210 halStatus = sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam);
1211 if (eHAL_STATUS_SUCCESS != halStatus)
1212 {
c_hpothuffdb5272013-10-02 16:42:35 +05301213 hddLog(VOS_TRACE_LEVEL_ERROR,
1214 "%s: sme_ConfigureResumeReq return failure %d", __func__, halStatus);
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301215 vos_mem_free(wlanResumeParam);
1216 }
1217
1218 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
1219
Amar Singhalf8ba2b82013-12-02 12:54:38 -08001220 if (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid) {
1221 pHddCtx->configuredMcastBcastFilter =
1222 pHddCtx->sus_res_mcastbcast_filter;
1223 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_FALSE;
1224 }
Amar Singhald53568e2013-09-26 11:03:45 -07001225
1226 hddLog(VOS_TRACE_LEVEL_INFO,
1227 "offload: in hdd_conf_resume_ind, restoring configuredMcastBcastFilter");
1228 hddLog(VOS_TRACE_LEVEL_INFO, "configuredMcastBcastFilter = %d",
1229 pHddCtx->configuredMcastBcastFilter);
Amar Singhal49fdfd52013-08-13 13:25:12 -07001230
Chilam Ngc4244af2013-04-01 15:37:32 -07001231
madan mohan koyyalamudibfd9cef2013-07-01 18:39:37 +05301232#ifdef WLAN_FEATURE_PACKET_FILTERING
1233 /* Filer was applied during suspend inditication
1234 * clear it when we resume.
1235 */
1236 wlan_hdd_set_mc_addr_list(pAdapter, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001237#endif
1238}
Jeff Johnson295189b2012-06-20 16:38:30 -07001239
Jeff Johnson295189b2012-06-20 16:38:30 -07001240//Suspend routine registered with Android OS
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001241void hdd_suspend_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001242{
1243 hdd_context_t *pHddCtx = NULL;
1244 v_CONTEXT_t pVosContext = NULL;
1245
Jeff Johnson295189b2012-06-20 16:38:30 -07001246 VOS_STATUS status;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301247 hdd_adapter_t *pAdapter = NULL;
1248 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301249 bool hdd_enter_bmps = FALSE;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001250
Jeff Johnson295189b2012-06-20 16:38:30 -07001251 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__);
1252
1253 //Get the global VOSS context.
1254 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1255 if(!pVosContext) {
1256 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1257 return;
1258 }
1259
1260 //Get the HDD context.
1261 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1262
1263 if(!pHddCtx) {
1264 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1265 return;
1266 }
1267
1268 if (pHddCtx->isLogpInProgress) {
1269 hddLog(VOS_TRACE_LEVEL_ERROR,
1270 "%s: Ignore suspend wlan, LOGP in progress!", __func__);
1271 return;
1272 }
1273
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301274 hdd_set_pwrparams(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001275 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1276 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1277 {
1278 pAdapter = pAdapterNode->pAdapter;
1279 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001280 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001281 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
1282
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001283 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001284 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1285 pAdapterNode = pNext;
1286 continue;
1287 }
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301288 /* Avoid multiple enter/exit BMPS in this while loop using
1289 * hdd_enter_bmps flag
1290 */
1291 if (FALSE == hdd_enter_bmps && (BMPS == pmcGetPmcState(pHddCtx->hHal)))
1292 {
1293 hdd_enter_bmps = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001294
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301295 /* If device was already in BMPS, and dynamic DTIM is set,
1296 * exit(set the device to full power) and enter BMPS again
1297 * to reflect new DTIM value */
1298 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
1299
1300 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
1301
1302 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1303 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001304#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1305 if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1306 {
1307 //stop the interface before putting the chip to standby
1308 netif_tx_disable(pAdapter->dev);
1309 netif_carrier_off(pAdapter->dev);
1310 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301311 else if (pHddCtx->cfg_ini->nEnableSuspend ==
Jeff Johnson295189b2012-06-20 16:38:30 -07001312 WLAN_MAP_SUSPEND_TO_DEEP_SLEEP)
1313 {
1314 //Execute deep sleep procedure
1315 hdd_enter_deep_sleep(pHddCtx, pAdapter);
1316 }
1317#endif
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301318
1319 /*Suspend notification sent down to driver*/
1320 hdd_conf_suspend_ind(pHddCtx, pAdapter);
1321
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301322 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1323 pAdapterNode = pNext;
1324 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301325 pHddCtx->hdd_wlan_suspended = TRUE;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301326
Jeff Johnson295189b2012-06-20 16:38:30 -07001327#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1328 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1329 {
1330 hdd_enter_standby(pHddCtx);
1331 }
1332#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001333
1334 return;
1335}
1336
1337static void hdd_PowerStateChangedCB
1338(
1339 v_PVOID_t callbackContext,
1340 tPmcState newState
1341)
1342{
1343 hdd_context_t *pHddCtx = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07001344 /* if the driver was not in BMPS during early suspend,
1345 * the dynamic DTIM is now updated at Riva */
1346 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended
1347 && pHddCtx->cfg_ini->enableDynamicDTIM
1348 && (pHddCtx->hdd_ignore_dtim_enabled == FALSE))
1349 {
1350 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1351 }
1352 spin_lock(&pHddCtx->filter_lock);
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301353 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended)
1354 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001355 spin_unlock(&pHddCtx->filter_lock);
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301356 if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid)
1357 {
Amar Singhald53568e2013-09-26 11:03:45 -07001358 pHddCtx->sus_res_mcastbcast_filter =
1359 pHddCtx->configuredMcastBcastFilter;
1360 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
1361
1362 hddLog(VOS_TRACE_LEVEL_INFO, "offload: callback to associated");
1363 hddLog(VOS_TRACE_LEVEL_INFO, "saving configuredMcastBcastFilter = %d",
1364 pHddCtx->configuredMcastBcastFilter);
1365 hddLog(VOS_TRACE_LEVEL_INFO,
1366 "offload: calling hdd_conf_mcastbcast_filter");
1367
1368 }
1369
Jeff Johnson295189b2012-06-20 16:38:30 -07001370 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001371 if(pHddCtx->hdd_mcastbcast_filter_set != TRUE)
1372 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__);
1373 }
Amar Singhal49fdfd52013-08-13 13:25:12 -07001374 else
Mihir Shete793209f2014-01-06 11:01:12 +05301375 {
1376 /* Android framework can send resume request when the WCN chip is
1377 * in IMPS mode. When the chip exits IMPS mode the firmware will
1378 * restore all the registers to the state they were before the chip
1379 * entered IMPS and so our hardware filter settings confgured by the
1380 * resume request will be lost. So reconfigure the filters on detecting
1381 * a change in the power state of the WCN chip.
1382 */
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301383 spin_unlock(&pHddCtx->filter_lock);
Mihir Shete793209f2014-01-06 11:01:12 +05301384 if (IMPS != newState)
1385 {
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301386 spin_lock(&pHddCtx->filter_lock);
Mihir Shete793209f2014-01-06 11:01:12 +05301387 if (FALSE == pHddCtx->hdd_wlan_suspended)
1388 {
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301389 spin_unlock(&pHddCtx->filter_lock);
Mihir Shete793209f2014-01-06 11:01:12 +05301390 hddLog(VOS_TRACE_LEVEL_INFO,
1391 "Not in IMPS/BMPS and suspended state");
1392 hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
1393 }
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301394 else
1395 {
1396 spin_unlock(&pHddCtx->filter_lock);
1397 }
Mihir Shete793209f2014-01-06 11:01:12 +05301398 }
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301399 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001400}
1401
1402
1403
1404void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx)
1405{
1406 v_CONTEXT_t pVosContext;
1407 tHalHandle smeContext;
1408
1409 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1410 if (NULL == pVosContext)
1411 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001412 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001413 return;
1414 }
1415 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1416 if (NULL == smeContext)
1417 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001418 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001419 return;
1420 }
1421
1422 spin_lock_init(&pHddCtx->filter_lock);
1423 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1424 pHddCtx->cfg_ini->nEnableSuspend)
1425 {
1426 pmcRegisterDeviceStateUpdateInd(smeContext,
1427 hdd_PowerStateChangedCB, pHddCtx);
1428 }
1429}
1430
1431void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx)
1432{
1433 v_CONTEXT_t pVosContext;
1434 tHalHandle smeContext;
1435
1436 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1437 if (NULL == pVosContext)
1438 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001439 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001440 return;
1441 }
1442 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1443 if (NULL == smeContext)
1444 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001445 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001446 return;
1447 }
1448
1449 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1450 pHddCtx->cfg_ini->nEnableSuspend)
1451 {
1452 pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB);
1453 }
1454}
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301455
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301456#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301457void hdd_conf_gtk_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301458{
1459 eHalStatus ret;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301460 tSirGtkOffloadParams hddGtkOffloadReqParams;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301461 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1462
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301463 if(fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301464 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301465 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1466 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags ))
1467 {
1468 vos_mem_copy(&hddGtkOffloadReqParams,
1469 &pHddStaCtx->gtkOffloadReqParams,
1470 sizeof (tSirGtkOffloadParams));
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301471
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301472 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1473 &hddGtkOffloadReqParams, pAdapter->sessionId);
1474 if (eHAL_STATUS_SUCCESS != ret)
1475 {
1476 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1477 "%s: sme_SetGTKOffload failed, returned %d",
1478 __func__, ret);
1479 return;
1480 }
1481
1482 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1483 "%s: sme_SetGTKOffload successfull", __func__);
1484 }
1485
1486 }
1487 else
1488 {
1489 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1490 (0 == memcmp(&pHddStaCtx->gtkOffloadReqParams.bssId,
1491 &pHddStaCtx->conn_info.bssId, WNI_CFG_BSSID_LEN)) &&
1492 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags))
1493 {
1494
1495 /* Host driver has previously offloaded GTK rekey */
1496 ret = sme_GetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301497 wlan_hdd_cfg80211_update_replayCounterCallback,
1498 pAdapter, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301499 if (eHAL_STATUS_SUCCESS != ret)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301500
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301501 {
1502 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1503 "%s: sme_GetGTKOffload failed, returned %d",
1504 __func__, ret);
1505 return;
1506 }
1507 else
1508 {
1509 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1510 "%s: sme_GetGTKOffload successful",
1511 __func__);
1512
1513 /* Sending GTK offload dissable */
1514 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
1515 sizeof (tSirGtkOffloadParams));
1516 hddGtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE;
1517 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301518 &hddGtkOffloadReqParams, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301519 if (eHAL_STATUS_SUCCESS != ret)
1520 {
1521 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1522 "%s: failed to dissable GTK offload, returned %d",
1523 __func__, ret);
1524 return;
1525 }
1526 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1527 "%s: successfully dissabled GTK offload request to HAL",
1528 __func__);
1529 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301530 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301531 }
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301532 return;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301533}
1534#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
Jeff Johnson295189b2012-06-20 16:38:30 -07001535
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001536void hdd_resume_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001537{
1538 hdd_context_t *pHddCtx = NULL;
1539 hdd_adapter_t *pAdapter = NULL;
1540 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1541 VOS_STATUS status;
1542 v_CONTEXT_t pVosContext = NULL;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001543
Jeff Johnson295189b2012-06-20 16:38:30 -07001544 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
1545
1546 //Get the global VOSS context.
1547 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1548 if(!pVosContext) {
1549 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1550 return;
1551 }
1552
1553 //Get the HDD context.
1554 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1555
1556 if(!pHddCtx) {
1557 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1558 return;
1559 }
1560
Agarwal Ashish971c2882013-10-30 20:11:12 +05301561 if (pHddCtx->isLogpInProgress)
1562 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001563 hddLog(VOS_TRACE_LEVEL_INFO,
1564 "%s: Ignore resume wlan, LOGP in progress!", __func__);
1565 return;
1566 }
1567
Jeff Johnson295189b2012-06-20 16:38:30 -07001568 pHddCtx->hdd_wlan_suspended = FALSE;
1569 /*loop through all adapters. Concurrency */
1570 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1571
1572 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1573 {
1574 pAdapter = pAdapterNode->pAdapter;
1575 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001576 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001577 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001578 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001579 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1580 pAdapterNode = pNext;
1581 continue;
1582 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301583
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301584
Jeff Johnson295189b2012-06-20 16:38:30 -07001585#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1586 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP)
1587 {
1588 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__);
1589 hdd_exit_deep_sleep(pAdapter);
1590 }
1591#endif
1592
1593 if(pHddCtx->hdd_ignore_dtim_enabled == TRUE)
1594 {
1595 /*Switch back to DTIM 1*/
1596 tSirSetPowerParamsReq powerRequest = { 0 };
1597
1598 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
1599 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07001600 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001601
1602 /*Disabled ModulatedDTIM if enabled on suspend*/
1603 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1604 powerRequest.uDTIMPeriod = 0;
1605
1606 /* Update ignoreDTIM and ListedInterval in CFG with default values */
1607 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1608 NULL, eANI_BOOLEAN_FALSE);
1609 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1610 NULL, eANI_BOOLEAN_FALSE);
1611
1612 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001613 "Switch to DTIM%d",powerRequest.uListenInterval);
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08001614 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001615
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301616 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
1617 {
1618 /* put the device into full power */
1619 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001620
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301621 /* put the device back into BMPS */
1622 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
Jeff Johnson295189b2012-06-20 16:38:30 -07001623
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301624 pHddCtx->hdd_ignore_dtim_enabled = FALSE;
1625 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001626 }
1627
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301628 hdd_conf_resume_ind(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001629 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1630 pAdapterNode = pNext;
1631 }
1632
1633#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1634 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY)
1635 {
1636 hdd_exit_standby(pHddCtx);
1637 }
1638#endif
1639
Jeff Johnson295189b2012-06-20 16:38:30 -07001640 return;
1641}
1642
Jeff Johnson295189b2012-06-20 16:38:30 -07001643VOS_STATUS hdd_wlan_reset_initialization(void)
1644{
Jeff Johnson295189b2012-06-20 16:38:30 -07001645 v_CONTEXT_t pVosContext = NULL;
1646
1647 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1648
1649 //Get the global VOSS context.
1650 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1651 if(!pVosContext)
1652 {
1653 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1654 return VOS_STATUS_E_FAILURE;
1655 }
1656
1657 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__);
1658
1659 // Prevent the phone from going to sleep
1660 hdd_prevent_suspend();
1661
Jeff Johnson295189b2012-06-20 16:38:30 -07001662 return VOS_STATUS_SUCCESS;
1663}
1664
1665
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001666/*
1667 * Based on the ioctl command recieved by HDD, put WLAN driver
1668 * into the quiet mode. This is the same as the early suspend
1669 * notification that driver used to listen
1670 */
1671void hdd_set_wlan_suspend_mode(bool suspend)
Jeff Johnson295189b2012-06-20 16:38:30 -07001672{
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001673 if (suspend)
1674 hdd_suspend_wlan();
1675 else
1676 hdd_resume_wlan();
Jeff Johnson295189b2012-06-20 16:38:30 -07001677}
1678
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001679static void hdd_ssr_timer_init(void)
1680{
1681 init_timer(&ssr_timer);
1682}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001683
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001684static void hdd_ssr_timer_del(void)
1685{
1686 del_timer(&ssr_timer);
1687 ssr_timer_started = false;
1688}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001689
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001690static void hdd_ssr_timer_cb(unsigned long data)
1691{
1692 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD SSR timer expired", __func__);
Sameer Thalappile5637f42013-08-07 15:46:55 -07001693
1694#ifdef WCN_PRONTO
1695 if (wcnss_hardware_type() == WCNSS_PRONTO_HW)
1696 wcnss_pronto_log_debug_regs();
1697#endif
1698
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001699 VOS_BUG(0);
1700}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001701
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001702static void hdd_ssr_timer_start(int msec)
1703{
1704 if(ssr_timer_started)
1705 {
1706 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: trying to start SSR timer when it's running"
1707 ,__func__);
1708 }
1709 ssr_timer.expires = jiffies + msecs_to_jiffies(msec);
1710 ssr_timer.function = hdd_ssr_timer_cb;
1711 add_timer(&ssr_timer);
1712 ssr_timer_started = true;
1713}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001714
Jeff Johnson295189b2012-06-20 16:38:30 -07001715/* the HDD interface to WLAN driver shutdown,
1716 * the primary shutdown function in SSR
1717 */
1718VOS_STATUS hdd_wlan_shutdown(void)
1719{
1720 VOS_STATUS vosStatus;
1721 v_CONTEXT_t pVosContext = NULL;
1722 hdd_context_t *pHddCtx = NULL;
1723 pVosSchedContext vosSchedContext = NULL;
c_hpothuffdb5272013-10-02 16:42:35 +05301724 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07001725
1726 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__);
1727
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001728 /* if re-init never happens, then do SSR1 */
1729 hdd_ssr_timer_init();
1730 hdd_ssr_timer_start(HDD_SSR_BRING_UP_TIME);
1731
Jeff Johnson295189b2012-06-20 16:38:30 -07001732 /* Get the global VOSS context. */
1733 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1734 if(!pVosContext) {
1735 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1736 return VOS_STATUS_E_FAILURE;
1737 }
1738 /* Get the HDD context. */
1739 pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1740 if(!pHddCtx) {
1741 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1742 return VOS_STATUS_E_FAILURE;
1743 }
c_hpothud662a352013-12-26 15:09:12 +05301744
1745 //Stop the traffic monitor timer
1746 if ( VOS_TIMER_STATE_RUNNING ==
1747 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
1748 {
1749 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
1750 }
1751
Jeff Johnson295189b2012-06-20 16:38:30 -07001752 hdd_reset_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001753 /* DeRegister with platform driver as client for Suspend/Resume */
1754 vosStatus = hddDeregisterPmOps(pHddCtx);
1755 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1756 {
1757 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
1758 }
1759
1760 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
1761 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1762 {
1763 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
1764 }
1765
1766 /* Disable IMPS/BMPS as we do not want the device to enter any power
1767 * save mode on its own during reset sequence
1768 */
1769 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1770 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1771 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1772
1773 vosSchedContext = get_vos_sched_ctxt();
1774
1775 /* Wakeup all driver threads */
1776 if(TRUE == pHddCtx->isMcThreadSuspended){
1777 complete(&vosSchedContext->ResumeMcEvent);
1778 pHddCtx->isMcThreadSuspended= FALSE;
1779 }
1780 if(TRUE == pHddCtx->isTxThreadSuspended){
1781 complete(&vosSchedContext->ResumeTxEvent);
1782 pHddCtx->isTxThreadSuspended= FALSE;
1783 }
1784 if(TRUE == pHddCtx->isRxThreadSuspended){
1785 complete(&vosSchedContext->ResumeRxEvent);
1786 pHddCtx->isRxThreadSuspended= FALSE;
1787 }
1788 /* Reset the Suspend Variable */
1789 pHddCtx->isWlanSuspended = FALSE;
1790
1791 /* Stop all the threads; we do not want any messages to be a processed,
1792 * any more and the best way to ensure that is to terminate the threads
1793 * gracefully.
1794 */
1795 /* Wait for MC to exit */
1796 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
1797 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
1798 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
1799 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
c_hpothuffdb5272013-10-02 16:42:35 +05301800 ret = wait_for_completion_interruptible(&vosSchedContext->McShutdown);
1801 if (0 >= ret)
1802 {
1803 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:wait on McShutdown failed %ld",
1804 __func__, ret);
1805 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001806
1807 /* Wait for TX to exit */
1808 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
1809 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
1810 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
1811 wake_up_interruptible(&vosSchedContext->txWaitQueue);
c_hpothuffdb5272013-10-02 16:42:35 +05301812 ret = wait_for_completion_interruptible(&vosSchedContext->TxShutdown);
1813 if (0 >= ret)
1814 {
1815 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:wait on TxShutdown failed %ld",
1816 __func__, ret);
1817 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001818
1819 /* Wait for RX to exit */
1820 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
1821 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
1822 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
1823 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
c_hpothuffdb5272013-10-02 16:42:35 +05301824
1825 ret = wait_for_completion_interruptible(&vosSchedContext->RxShutdown);
1826 if (0 >= ret)
1827 {
1828 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:wait on RxShutdown failed %ld",
1829 __func__, ret);
1830 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001831
1832#ifdef WLAN_BTAMP_FEATURE
1833 vosStatus = WLANBAP_Stop(pVosContext);
1834 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1835 {
1836 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1837 "%s: Failed to stop BAP",__func__);
1838 }
1839#endif //WLAN_BTAMP_FEATURE
1840 vosStatus = vos_wda_shutdown(pVosContext);
c_hpothuffdb5272013-10-02 16:42:35 +05301841 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1842 {
1843 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1844 "%s: Failed to stop wda %d", __func__, vosStatus);
1845 VOS_ASSERT(0);
1846 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001847
1848 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
1849 /* Stop SME - Cannot invoke vos_stop as vos_stop relies
1850 * on threads being running to process the SYS Stop
1851 */
Kiet Lama72a2322013-11-15 11:18:11 +05301852 vosStatus = sme_Stop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
c_hpothuffdb5272013-10-02 16:42:35 +05301853 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1854 {
1855 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1856 "%s: Failed to stop sme %d", __func__, vosStatus);
1857 VOS_ASSERT(0);
1858 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001859
1860 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
1861 /* Stop MAC (PE and HAL) */
1862 vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
c_hpothuffdb5272013-10-02 16:42:35 +05301863 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1864 {
1865 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1866 "%s: Failed to stop mac %d", __func__, vosStatus);
1867 VOS_ASSERT(0);
1868 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001869
1870 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
1871 /* Stop TL */
1872 vosStatus = WLANTL_Stop(pVosContext);
c_hpothuffdb5272013-10-02 16:42:35 +05301873 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1874 {
1875 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1876 "%s: Failed to stop TL %d", __func__, vosStatus);
1877 VOS_ASSERT(0);
1878 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001879
Jeff Johnson295189b2012-06-20 16:38:30 -07001880 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001881 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__);
1882 /* Clean up message queues of TX and MC thread */
1883 vos_sched_flush_mc_mqs(vosSchedContext);
1884 vos_sched_flush_tx_mqs(vosSchedContext);
1885 vos_sched_flush_rx_mqs(vosSchedContext);
1886
1887 /* Deinit all the TX and MC queues */
1888 vos_sched_deinit_mqs(vosSchedContext);
1889 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__);
1890
1891 /* shutdown VOSS */
1892 vos_shutdown(pVosContext);
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05301893
1894 /*mac context has already been released in mac_close call
1895 so setting it to NULL in hdd context*/
1896 pHddCtx->hHal = (tHalHandle)NULL;
1897
Jeff Johnson295189b2012-06-20 16:38:30 -07001898 if (free_riva_power_on_lock("wlan"))
1899 {
1900 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
1901 __func__);
1902 }
1903 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete"
1904 ,__func__);
1905 return VOS_STATUS_SUCCESS;
1906}
1907
1908
1909
1910/* the HDD interface to WLAN driver re-init.
1911 * This is called to initialize/start WLAN driver after a shutdown.
1912 */
1913VOS_STATUS hdd_wlan_re_init(void)
1914{
1915 VOS_STATUS vosStatus;
1916 v_CONTEXT_t pVosContext = NULL;
1917 hdd_context_t *pHddCtx = NULL;
1918 eHalStatus halStatus;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07001919#ifdef HAVE_WCNSS_CAL_DOWNLOAD
1920 int max_retries = 0;
1921#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001922#ifdef WLAN_BTAMP_FEATURE
1923 hdd_config_t *pConfig = NULL;
1924 WLANBAP_ConfigType btAmpConfig;
1925#endif
1926
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001927 hdd_ssr_timer_del();
Jeff Johnson295189b2012-06-20 16:38:30 -07001928 hdd_prevent_suspend();
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001929
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07001930#ifdef HAVE_WCNSS_CAL_DOWNLOAD
1931 /* wait until WCNSS driver downloads NV */
1932 while (!wcnss_device_ready() && 5 >= ++max_retries) {
1933 msleep(1000);
1934 }
1935 if (max_retries >= 5) {
1936 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
1937 goto err_re_init;
1938 }
1939#endif
1940
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07001941 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, TRUE);
1942
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001943 /* The driver should always be initialized in STA mode after SSR */
1944 hdd_set_conparam(0);
1945
Jeff Johnson295189b2012-06-20 16:38:30 -07001946 /* Re-open VOSS, it is a re-open b'se control transport was never closed. */
1947 vosStatus = vos_open(&pVosContext, 0);
1948 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1949 {
1950 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
1951 goto err_re_init;
1952 }
1953
1954 /* Get the HDD context. */
1955 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1956 if(!pHddCtx)
1957 {
1958 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1959 goto err_vosclose;
1960 }
1961
1962 /* Save the hal context in Adapter */
1963 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
1964 if ( NULL == pHddCtx->hHal )
1965 {
1966 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
1967 goto err_vosclose;
1968 }
1969
1970 /* Set the SME configuration parameters. */
1971 vosStatus = hdd_set_sme_config(pHddCtx);
1972 if ( VOS_STATUS_SUCCESS != vosStatus )
1973 {
1974 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
1975 goto err_vosclose;
1976 }
1977
1978 /* Initialize the WMM module */
1979 vosStatus = hdd_wmm_init(pHddCtx);
1980 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
1981 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001982 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001983 goto err_vosclose;
1984 }
1985
1986 vosStatus = vos_preStart( pHddCtx->pvosContext );
1987 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1988 {
1989 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
1990 goto err_vosclose;
1991 }
1992
1993 /* In the integrated architecture we update the configuration from
1994 the INI file and from NV before vOSS has been started so that
1995 the final contents are available to send down to the cCPU */
1996 /* Apply the cfg.ini to cfg.dat */
1997 if (FALSE == hdd_update_config_dat(pHddCtx))
1998 {
1999 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
2000 goto err_vosclose;
2001 }
2002
2003 /* Set the MAC Address, currently this is used by HAL to add self sta.
2004 * Remove this once self sta is added as part of session open. */
2005 halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID,
2006 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
2007 sizeof(pHddCtx->cfg_ini->intfMacAddr[0]));
2008 if (!HAL_STATUS_SUCCESS(halStatus))
2009 {
2010 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
2011 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus);
2012 goto err_vosclose;
2013 }
2014
2015 /* Start VOSS which starts up the SME/MAC/HAL modules and everything else
2016 Note: Firmware image will be read and downloaded inside vos_start API */
2017 vosStatus = vos_start( pVosContext );
2018 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2019 {
2020 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
2021 goto err_vosclose;
2022 }
2023
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07002024 /* Exchange capability info between Host and FW and also get versioning info from FW */
2025 hdd_exchange_version_and_caps(pHddCtx);
2026
Jeff Johnson295189b2012-06-20 16:38:30 -07002027 vosStatus = hdd_post_voss_start_config( pHddCtx );
2028 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2029 {
2030 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
2031 __func__);
2032 goto err_vosstop;
2033 }
2034
2035#ifdef WLAN_BTAMP_FEATURE
2036 vosStatus = WLANBAP_Open(pVosContext);
2037 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
2038 {
2039 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2040 "%s: Failed to open BAP",__func__);
2041 goto err_vosstop;
2042 }
2043 vosStatus = BSL_Init(pVosContext);
2044 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
2045 {
2046 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2047 "%s: Failed to Init BSL",__func__);
2048 goto err_bap_close;
2049 }
2050 vosStatus = WLANBAP_Start(pVosContext);
2051 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2052 {
2053 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2054 "%s: Failed to start TL",__func__);
2055 goto err_bap_close;
2056 }
2057 pConfig = pHddCtx->cfg_ini;
2058 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
2059 vosStatus = WLANBAP_SetConfig(&btAmpConfig);
2060#endif //WLAN_BTAMP_FEATURE
2061
2062 /* Restart all adapters */
2063 hdd_start_all_adapters(pHddCtx);
2064 pHddCtx->isLogpInProgress = FALSE;
Sameer Thalappilb511beb2013-09-09 17:11:51 -07002065 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07002066 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002067 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002068
2069 /* Register with platform driver as client for Suspend/Resume */
2070 vosStatus = hddRegisterPmOps(pHddCtx);
2071 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2072 {
2073 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
2074 goto err_bap_stop;
2075 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002076 /* Allow the phone to go to sleep */
2077 hdd_allow_suspend();
2078 /* register for riva power on lock */
2079 if (req_riva_power_on_lock("wlan"))
2080 {
2081 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
2082 __func__);
2083 goto err_unregister_pmops;
2084 }
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07002085 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07002086 goto success;
2087
2088err_unregister_pmops:
2089 hddDeregisterPmOps(pHddCtx);
2090
2091err_bap_stop:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002092#ifdef CONFIG_HAS_EARLYSUSPEND
2093 hdd_unregister_mcast_bcast_filter(pHddCtx);
2094#endif
2095 hdd_close_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002096#ifdef WLAN_BTAMP_FEATURE
Jeff Johnson32d95a32012-09-10 13:15:23 -07002097 WLANBAP_Stop(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07002098#endif
2099
2100#ifdef WLAN_BTAMP_FEATURE
2101err_bap_close:
2102 WLANBAP_Close(pVosContext);
2103#endif
2104
2105err_vosstop:
2106 vos_stop(pVosContext);
2107
2108err_vosclose:
2109 vos_close(pVosContext);
2110 vos_sched_close(pVosContext);
2111 if (pHddCtx)
2112 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002113 /* Unregister the Net Device Notifier */
2114 unregister_netdevice_notifier(&hdd_netdev_notifier);
2115 /* Clean up HDD Nlink Service */
2116 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07002117#ifdef WLAN_KD_READY_NOTIFIER
2118 nl_srv_exit(pHddCtx->ptt_pid);
2119#else
Jeff Johnson295189b2012-06-20 16:38:30 -07002120 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07002121#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07002122 /* Free up dynamically allocated members inside HDD Adapter */
2123 kfree(pHddCtx->cfg_ini);
2124 pHddCtx->cfg_ini= NULL;
2125
Jeff Johnson295189b2012-06-20 16:38:30 -07002126 wiphy_unregister(pHddCtx->wiphy);
2127 wiphy_free(pHddCtx->wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07002128 }
2129 vos_preClose(&pVosContext);
2130
2131#ifdef MEMORY_DEBUG
2132 vos_mem_exit();
2133#endif
2134
2135err_re_init:
2136 /* Allow the phone to go to sleep */
2137 hdd_allow_suspend();
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07002138 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07002139 VOS_BUG(0);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002140 return -EPERM;
Jeff Johnson295189b2012-06-20 16:38:30 -07002141
2142success:
2143 /* Trigger replay of BTC events */
2144 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
2145 return VOS_STATUS_SUCCESS;
2146}