blob: cd212ab84ddd194ce8c57607b6cd058584dd330b [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Kiet Lamaa8e15a2014-02-11 23:30:06 -08002 * Copyright (c) 2012-2013 Qualcomm Atheros, Inc.
3 * All Rights Reserved.
4 * Qualcomm Atheros Confidential and Proprietary.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08005 */
Jeff Johnson295189b2012-06-20 16:38:30 -07006/**=============================================================================
7* wlan_hdd_early_suspend.c
8*
9* \brief power management functions
10*
11* Description
12* Copyright 2009 (c) Qualcomm, Incorporated.
13* All Rights Reserved.
14* Qualcomm Confidential and Proprietary.
15*
16==============================================================================**/
17/* $HEADER$ */
18
19/**-----------------------------------------------------------------------------
20* Include files
21* ----------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -070022
23#include <linux/pm.h>
24#include <linux/wait.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070025#include <wlan_hdd_includes.h>
26#include <wlan_qct_driver.h>
27#include <linux/wakelock.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070028
29#include "halTypes.h"
30#include "sme_Api.h"
31#include <vos_api.h>
32#include "vos_power.h"
33#include <vos_sched.h>
34#include <macInitApi.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070035#include <wlan_qct_sys.h>
36#include <wlan_btc_svc.h>
37#include <wlan_nlink_common.h>
38#include <wlan_hdd_main.h>
39#include <wlan_hdd_assoc.h>
40#include <wlan_hdd_dev_pwr.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070041#include <wlan_nlink_srv.h>
42#include <wlan_hdd_misc.h>
43
Jeff Johnson295189b2012-06-20 16:38:30 -070044#include <linux/semaphore.h>
45#include <wlan_hdd_hostapd.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070046#include "cfgApi.h"
47
48#ifdef WLAN_BTAMP_FEATURE
49#include "bapApi.h"
50#include "bap_hdd_main.h"
51#include "bap_hdd_misc.h"
52#endif
53
Jeff Johnsone7245742012-09-05 17:12:55 -070054#include <linux/wcnss_wlan.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070055#include <linux/inetdevice.h>
56#include <wlan_hdd_cfg.h>
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053057#include <wlan_hdd_cfg80211.h>
Gopichand Nakkala746a9452013-06-11 12:45:54 +053058#include <net/addrconf.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070059/**-----------------------------------------------------------------------------
60* Preprocessor definitions and constants
61* ----------------------------------------------------------------------------*/
62
63/**-----------------------------------------------------------------------------
64* Type declarations
65* ----------------------------------------------------------------------------*/
66
67/**-----------------------------------------------------------------------------
68* Function and variables declarations
69* ----------------------------------------------------------------------------*/
70#include "wlan_hdd_power.h"
71#include "wlan_hdd_packet_filtering.h"
72
Sameer Thalappile5637f42013-08-07 15:46:55 -070073#define HDD_SSR_BRING_UP_TIME 180000
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +053074#define NS_DEFAULT_SLOT_INDEX 4
75#define NS_EXTENDED_SLOT_INDEX 18
Jeff Johnson295189b2012-06-20 16:38:30 -070076
77static eHalStatus g_full_pwr_status;
78static eHalStatus g_standby_status;
79
80extern VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx);
81extern VOS_STATUS vos_chipExitDeepSleepVREGHandler(
82 vos_call_status_type* status,
83 vos_power_cb_type callback,
84 v_PVOID_t user_data);
85extern void hdd_wlan_initial_scan(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070086
87extern struct notifier_block hdd_netdev_notifier;
Jeff Johnson295189b2012-06-20 16:38:30 -070088extern tVOS_CON_MODE hdd_get_conparam ( void );
Jeff Johnson295189b2012-06-20 16:38:30 -070089
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -070090static struct timer_list ssr_timer;
91static bool ssr_timer_started;
Jeff Johnson295189b2012-06-20 16:38:30 -070092
93//Callback invoked by PMC to report status of standby request
94void hdd_suspend_standby_cbk (void *callbackContext, eHalStatus status)
95{
96 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
97 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Standby status = %d", __func__, status);
98 g_standby_status = status;
99
100 if(eHAL_STATUS_SUCCESS == status)
101 {
102 pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY;
103 }
104 else
105 {
106 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__);
107 }
108
109 complete(&pHddCtx->standby_comp_var);
110}
111
112//Callback invoked by PMC to report status of full power request
113void hdd_suspend_full_pwr_callback(void *callbackContext, eHalStatus status)
114{
115 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
116 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Full Power status = %d", __func__, status);
117 g_full_pwr_status = status;
118
119 if(eHAL_STATUS_SUCCESS == status)
120 {
121 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
122 }
123 else
124 {
125 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
126 }
127
128 complete(&pHddCtx->full_pwr_comp_var);
129}
130
131eHalStatus hdd_exit_standby(hdd_context_t *pHddCtx)
132{
133 eHalStatus status = VOS_STATUS_SUCCESS;
c_hpothuffdb5272013-10-02 16:42:35 +0530134 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -0700135
136 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from standby",__func__);
137 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
138
139 g_full_pwr_status = eHAL_STATUS_FAILURE;
140 status = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback, pHddCtx,
141 eSME_FULL_PWR_NEEDED_BY_HDD);
142
143 if(status == eHAL_STATUS_PMC_PENDING)
144 {
145 //Block on a completion variable. Can't wait forever though
c_hpothuffdb5272013-10-02 16:42:35 +0530146 ret = wait_for_completion_interruptible_timeout(
147 &pHddCtx->full_pwr_comp_var,
148 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
149 if (0 >= ret)
150 {
151 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:wait on full_pwr_comp_var failed %ld",
152 __func__, ret);
153 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700154 status = g_full_pwr_status;
155 if(g_full_pwr_status != eHAL_STATUS_SUCCESS)
156 {
157 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
158 VOS_ASSERT(0);
159 goto failure;
160 }
161 }
162 else if(status != eHAL_STATUS_SUCCESS)
163 {
164 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d",
165 __func__, status);
166 VOS_ASSERT(0);
167 goto failure;
168 }
169 else
170 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
171
172failure:
173 //No blocking to reduce latency. No other device should be depending on WLAN
174 //to finish resume and WLAN won't be instantly on after resume
175 return status;
176}
177
178
179//Helper routine to put the chip into standby
180VOS_STATUS hdd_enter_standby(hdd_context_t *pHddCtx)
181{
182 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
183 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
c_hpothuffdb5272013-10-02 16:42:35 +0530184 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -0700185
186 //Disable IMPS/BMPS as we do not want the device to enter any power
187 //save mode on its own during suspend sequence
188 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
189 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
190
191 //Note we do not disable queues unnecessarily. Queues should already be disabled
192 //if STA is disconnected or the queue will be disabled as and when disconnect
193 //happens because of standby procedure.
194
195 //Ensure that device is in full power first. There is scope for optimization
196 //here especially in scenarios where PMC is already in IMPS or REQUEST_IMPS.
197 //Core s/w needs to be optimized to handle this. Until then we request full
198 //power before issuing request for standby.
199 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
200 g_full_pwr_status = eHAL_STATUS_FAILURE;
201 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback,
202 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
203
204 if(halStatus == eHAL_STATUS_PMC_PENDING)
205 {
206 //Block on a completion variable. Can't wait forever though
c_hpothuffdb5272013-10-02 16:42:35 +0530207 ret = wait_for_completion_interruptible_timeout(
208 &pHddCtx->full_pwr_comp_var,
209 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
210 if (0 >= ret)
211 {
212 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:wait on full_pwr_comp_var failed %ld",
213 __func__, ret);
214 }
215
Jeff Johnson295189b2012-06-20 16:38:30 -0700216 if(g_full_pwr_status != eHAL_STATUS_SUCCESS)
217 {
218 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower Failed",__func__);
219 VOS_ASSERT(0);
220 vosStatus = VOS_STATUS_E_FAILURE;
221 goto failure;
222 }
223 }
224 else if(halStatus != eHAL_STATUS_SUCCESS)
225 {
226 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d",
227 __func__, halStatus);
228 VOS_ASSERT(0);
229 vosStatus = VOS_STATUS_E_FAILURE;
230 goto failure;
231 }
232
233 if(pHddCtx->hdd_mcastbcast_filter_set == TRUE) {
234 hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
235 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
236 }
237
238 //Request standby. Standby will cause the STA to disassociate first. TX queues
239 //will be disabled (by HDD) when STA disconnects. You do not want to disable TX
240 //queues here. Also do not assert if the failure code is eHAL_STATUS_PMC_NOT_NOW as PMC
241 //will send this failure code in case of concurrent sessions. Power Save cannot be supported
242 //when there are concurrent sessions.
243 INIT_COMPLETION(pHddCtx->standby_comp_var);
244 g_standby_status = eHAL_STATUS_FAILURE;
245 halStatus = sme_RequestStandby(pHddCtx->hHal, hdd_suspend_standby_cbk, pHddCtx);
246
247 if (halStatus == eHAL_STATUS_PMC_PENDING)
248 {
249 //Wait till WLAN device enters standby mode
c_hpothuffdb5272013-10-02 16:42:35 +0530250 ret = wait_for_completion_timeout(&pHddCtx->standby_comp_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700251 msecs_to_jiffies(WLAN_WAIT_TIME_STANDBY));
c_hpothuffdb5272013-10-02 16:42:35 +0530252 if (0 >= ret)
253 {
254 hddLog(VOS_TRACE_LEVEL_ERROR,
255 FL("wait on standby_comp_var failed %ld"), ret);
256 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700257 if (g_standby_status != eHAL_STATUS_SUCCESS && g_standby_status != eHAL_STATUS_PMC_NOT_NOW)
258 {
259 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__);
260 VOS_ASSERT(0);
261 vosStatus = VOS_STATUS_E_FAILURE;
262 goto failure;
263 }
264 }
265 else if (halStatus != eHAL_STATUS_SUCCESS && halStatus != eHAL_STATUS_PMC_NOT_NOW) {
266 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed - status %d",
267 __func__, halStatus);
268 VOS_ASSERT(0);
269 vosStatus = VOS_STATUS_E_FAILURE;
270 goto failure;
271 }
272 else
273 pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY;
274
275failure:
276 //Restore IMPS config
277 if(pHddCtx->cfg_ini->fIsImpsEnabled)
278 sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
279
280 //Restore BMPS config
281 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
282 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
283
284 return vosStatus;
285}
286
287
288//Helper routine for Deep sleep entry
289VOS_STATUS hdd_enter_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter)
290{
291 eHalStatus halStatus;
292 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
293 vos_call_status_type callType;
c_hpothuffdb5272013-10-02 16:42:35 +0530294 long ret;
Jeff Johnsonbc676b42013-02-14 16:04:08 -0800295
Jeff Johnson295189b2012-06-20 16:38:30 -0700296 //Stop the Interface TX queue.
297 netif_tx_disable(pAdapter->dev);
298 netif_carrier_off(pAdapter->dev);
299
300 //Disable IMPS,BMPS as we do not want the device to enter any power
301 //save mode on it own during suspend sequence
302 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
303 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
304
305 //Ensure that device is in full power as we will touch H/W during vos_Stop
306 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
307 g_full_pwr_status = eHAL_STATUS_FAILURE;
308 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback,
309 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
310
311 if(halStatus == eHAL_STATUS_PMC_PENDING)
312 {
313 //Block on a completion variable. Can't wait forever though
c_hpothuffdb5272013-10-02 16:42:35 +0530314 ret = wait_for_completion_interruptible_timeout(
315 &pHddCtx->full_pwr_comp_var,
316 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
317 if (0 >= ret)
318 {
319 hddLog(VOS_TRACE_LEVEL_ERROR,
320 FL("wait on full_pwr_comp_var failed %ld"), ret);
321 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700322 if(g_full_pwr_status != eHAL_STATUS_SUCCESS){
323 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
324 VOS_ASSERT(0);
325 }
326 }
327 else if(halStatus != eHAL_STATUS_SUCCESS)
328 {
329 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Request for Full Power failed",__func__);
330 VOS_ASSERT(0);
331 }
332
333 //Issue a disconnect. This is required to inform the supplicant that
334 //STA is getting disassociated and for GUI to be updated properly
335 INIT_COMPLETION(pAdapter->disconnect_comp_var);
336 halStatus = sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED);
337
338 //Success implies disconnect command got queued up successfully
339 if(halStatus == eHAL_STATUS_SUCCESS)
340 {
341 //Block on a completion variable. Can't wait forever though.
c_hpothuffdb5272013-10-02 16:42:35 +0530342 ret = wait_for_completion_interruptible_timeout(
343 &pAdapter->disconnect_comp_var,
344 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
345 if (0 >= ret)
346 {
347 hddLog(VOS_TRACE_LEVEL_ERROR,
348 FL("wait on disconnect_comp_var failed %ld"), ret);
349 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700350 }
351
352
353 //None of the steps should fail after this. Continue even in case of failure
354 vosStatus = vos_stop( pHddCtx->pvosContext );
c_hpothuffdb5272013-10-02 16:42:35 +0530355 if( !VOS_IS_STATUS_SUCCESS( vosStatus ))
356 {
357 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: vos_stop return failed %d",
358 __func__, vosStatus);
359 VOS_ASSERT(0);
360 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700361
Jeff Johnson295189b2012-06-20 16:38:30 -0700362 vosStatus = vos_chipAssertDeepSleep( &callType, NULL, NULL );
c_hpothuffdb5272013-10-02 16:42:35 +0530363 if( VOS_IS_STATUS_SUCCESS( vosStatus ))
364 {
365 hddLog(VOS_TRACE_LEVEL_ERROR,
366 FL("vos_chipAssertDeepSleep return failed %d"), vosStatus);
367 VOS_ASSERT(0);
368 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700369
370 //Vote off any PMIC voltage supplies
371 vosStatus = vos_chipPowerDown(NULL, NULL, NULL);
c_hpothuffdb5272013-10-02 16:42:35 +0530372 if( !VOS_IS_STATUS_SUCCESS( vosStatus ))
373 {
374 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: vos_chipPowerDown return failed %d",
375 __func__, vosStatus);
376 VOS_ASSERT(0);
377 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700378
Jeff Johnson295189b2012-06-20 16:38:30 -0700379 pHddCtx->hdd_ps_state = eHDD_SUSPEND_DEEP_SLEEP;
380
381 //Restore IMPS config
382 if(pHddCtx->cfg_ini->fIsImpsEnabled)
383 sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
384
385 //Restore BMPS config
386 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
387 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
388
Jeff Johnson295189b2012-06-20 16:38:30 -0700389 return vosStatus;
390}
391
392VOS_STATUS hdd_exit_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter)
393{
394 VOS_STATUS vosStatus;
395 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -0700396
397 //Power Up Libra WLAN card first if not already powered up
398 vosStatus = vos_chipPowerUp(NULL,NULL,NULL);
399 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
400 {
c_hpothuffdb5272013-10-02 16:42:35 +0530401 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN not Powered Up."
Jeff Johnson295189b2012-06-20 16:38:30 -0700402 "exiting", __func__);
403 goto err_deep_sleep;
404 }
405
Jeff Johnson295189b2012-06-20 16:38:30 -0700406 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
407 "%s: calling hdd_set_sme_config",__func__);
408 vosStatus = hdd_set_sme_config( pHddCtx );
409 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
410 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
411 {
412 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
413 "%s: Failed in hdd_set_sme_config",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700414 goto err_deep_sleep;
Jeff Johnson295189b2012-06-20 16:38:30 -0700415 }
416
417 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
418 "%s: calling vos_start",__func__);
419 vosStatus = vos_start( pHddCtx->pvosContext );
420 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
421 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
422 {
423 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
424 "%s: Failed in vos_start",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700425 goto err_deep_sleep;
Jeff Johnson295189b2012-06-20 16:38:30 -0700426 }
427
428 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
429 "%s: calling hdd_post_voss_start_config",__func__);
430 vosStatus = hdd_post_voss_start_config( pHddCtx );
431 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
432 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
433 {
434 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
435 "%s: Failed in hdd_post_voss_start_config",__func__);
436 goto err_voss_stop;
437 }
438
439
440 //Open a SME session for future operation
441 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pHddCtx,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -0700442 (tANI_U8 *)&pAdapter->macAddressCurrent,
443 &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700444 if ( !HAL_STATUS_SUCCESS( halStatus ) )
445 {
Jeff Johnson0299d0a2013-10-30 12:37:43 -0700446 hddLog(VOS_TRACE_LEVEL_FATAL,"sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -0700447 halStatus, halStatus );
448 goto err_voss_stop;
449
450 }
451
452 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
453
454 //Trigger the initial scan
455 hdd_wlan_initial_scan(pHddCtx);
456
457 return VOS_STATUS_SUCCESS;
458
459err_voss_stop:
460 vos_stop(pHddCtx->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -0700461err_deep_sleep:
462 return VOS_STATUS_E_FAILURE;
463
464}
465
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530466/*
467 * Function: hdd_conf_hostoffload
468 * Central function to configure the supported offloads,
469 * either enable or disable them.
470 */
471void hdd_conf_hostoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
472{
473 hdd_context_t *pHddCtx = NULL;
474 v_CONTEXT_t *pVosContext = NULL;
475 VOS_STATUS vstatus = VOS_STATUS_E_FAILURE;
476
477 hddLog(VOS_TRACE_LEVEL_INFO, FL("Configuring offloads with flag: %d"),
478 fenable);
479
480 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
481
482 if (NULL == pVosContext)
483 {
484 hddLog(VOS_TRACE_LEVEL_ERROR, FL(" Global VOS context is Null"));
485 return;
486 }
487
488 //Get the HDD context.
489 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
490
491 if (NULL == pHddCtx)
492 {
493 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: HDD context is Null", __func__);
494 return;
495 }
496
497 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
498 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
499 {
500 if (fenable)
501 {
502 if (eConnectionState_Associated ==
503 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)
504 {
505 if ((pHddCtx->cfg_ini->fhostArpOffload))
506 {
507 /*
508 * Configure the ARP Offload.
509 * Even if it fails we have to reconfigure the MC/BC
510 * filter flag as we want RIVA not to drop BroadCast
511 * Packets
512 */
513 hddLog(VOS_TRACE_LEVEL_INFO,
514 FL("Calling ARP Offload with flag: %d"), fenable);
515 vstatus = hdd_conf_arp_offload(pAdapter, fenable);
516 pHddCtx->configuredMcastBcastFilter &=
517 ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST);
518
519 if (!VOS_IS_STATUS_SUCCESS(vstatus))
520 {
521 hddLog(VOS_TRACE_LEVEL_ERROR,
522 "Failed to enable ARPOFfloadFeature %d",
523 vstatus);
524 }
525 }
526 //Configure GTK_OFFLOAD
527#ifdef WLAN_FEATURE_GTK_OFFLOAD
528 hdd_conf_gtk_offload(pAdapter, fenable);
529#endif
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530530
531#ifdef WLAN_NS_OFFLOAD
532 if (pHddCtx->cfg_ini->fhostNSOffload)
533 {
534 /*
535 * Configure the NS Offload.
536 * Even if it fails we have to reconfigure the MC/BC filter flag
537 * as we want RIVA not to drop Multicast Packets
538 */
539
540 hddLog(VOS_TRACE_LEVEL_INFO,
541 FL("Calling NS Offload with flag: %d"), fenable);
542 hdd_conf_ns_offload(pAdapter, fenable);
543 pHddCtx->configuredMcastBcastFilter &=
544 ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST);
545 }
546#endif
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530547 }
548 }
549 else
550 {
551 //Disable ARPOFFLOAD
552 if (pHddCtx->cfg_ini->fhostArpOffload)
553 {
554 vstatus = hdd_conf_arp_offload(pAdapter, fenable);
555 if (!VOS_IS_STATUS_SUCCESS(vstatus))
556 {
557 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530558 "Failed to disable ARPOffload Feature %d", vstatus);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530559 }
560 }
561 //Disable GTK_OFFLOAD
562#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530563 hdd_conf_gtk_offload(pAdapter, fenable);
564#endif
565
566#ifdef WLAN_NS_OFFLOAD
567 //Disable NSOFFLOAD
568 if (pHddCtx->cfg_ini->fhostNSOffload)
569 {
570 hdd_conf_ns_offload(pAdapter, fenable);
571 }
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530572#endif
573 }
574 }
575 return;
576}
577
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530578#ifdef WLAN_NS_OFFLOAD
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530579void hdd_ipv6_notifier_work_queue(struct work_struct *work)
580{
581 hdd_adapter_t* pAdapter =
582 container_of(work, hdd_adapter_t, ipv6NotifierWorkQueue);
583 hdd_context_t *pHddCtx;
584 int status;
585
586 hddLog(LOG1, FL("Reconfiguring NS Offload"));
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530587
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530588 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
589 status = wlan_hdd_validate_context(pHddCtx);
590 if (0 != status)
591 {
592 hddLog(LOGE, FL("HDD context is invalid"));
593 return;
594 }
595
Deepthi Gowri5933f402014-01-23 17:48:24 +0530596 if ( VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid)
597 {
598 pHddCtx->sus_res_mcastbcast_filter =
599 pHddCtx->configuredMcastBcastFilter;
600 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
601 }
602
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530603 if ((eConnectionState_Associated ==
604 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)
Deepthi Gowri5933f402014-01-23 17:48:24 +0530605 && (pHddCtx->hdd_wlan_suspended))
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530606 {
607 // This invocation being part of the IPv6 registration callback,
608 // we are passing second parameter as 2 to avoid registration
609 // of IPv6 notifier again.
610 hdd_conf_ns_offload(pAdapter, 2);
611 }
612}
613
614static int wlan_hdd_ipv6_changed(struct notifier_block *nb,
615 unsigned long data, void *arg)
616{
617 struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)arg;
618 struct net_device *ndev = ifa->idev->dev;
619 hdd_adapter_t *pAdapter =
620 container_of(nb, struct hdd_adapter_s, ipv6_notifier);
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530621 hdd_context_t *pHddCtx;
622 int status;
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530623
624 if (pAdapter && pAdapter->dev == ndev)
625 {
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530626 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
627 status = wlan_hdd_validate_context(pHddCtx);
628 if (0 != status)
629 {
630 hddLog(LOGE, FL("HDD context is invalid"));
631 return NOTIFY_DONE;
632 }
633
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530634 schedule_work(&pAdapter->ipv6NotifierWorkQueue);
635 }
636
637 return NOTIFY_DONE;
638}
639
640/**----------------------------------------------------------------------------
641
642 \brief hdd_conf_ns_offload() - Configure NS offload
643
644 Called during SUSPEND to configure the NS offload (MC BC filter) which
645 reduces power consumption.
646
647 \param - pAdapter - Adapter context for which NS offload is to be configured
648 \param - fenable - 0 - disable.
649 1 - enable. (with IPv6 notifier registration)
650 2 - enable. (without IPv6 notifier registration)
651
652 \return - void
653
654 ---------------------------------------------------------------------------*/
655void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, int fenable)
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530656{
657 struct inet6_dev *in6_dev;
658 struct inet6_ifaddr *ifp;
659 struct list_head *p;
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530660 int slot_index = NS_DEFAULT_SLOT_INDEX;
661 tANI_U8 **selfIPv6Addr;
662 tANI_U8 *selfIPv6AddrValid;
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530663 tSirHostOffloadReq offLoadRequest;
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530664 hdd_context_t *pHddCtx;
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530665 tHalHandle halHandle;
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530666
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530667 int i = 0, slot = 0;
668 int ret = 0;
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530669 eHalStatus returnStatus;
670
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530671 ENTER();
672 hddLog(LOG1, FL(" fenable = %d"), fenable);
673
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530674 if (NULL == pAdapter)
675 {
676 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD adapter is Null"));
677 return;
678 }
679
680 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530681 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
682
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530683 ret = wlan_hdd_validate_context(pHddCtx);
684
685 if (0 != ret)
686 {
687 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
688 FL("HDD context is not valid"));
689 return;
690 }
691
692 if (sme_IsFeatureSupportedByFW(EXTENDED_NSOFFLOAD_SLOT))
693 {
694 slot_index = NS_EXTENDED_SLOT_INDEX;
695 }
696
697 hddLog(VOS_TRACE_LEVEL_INFO, FL("slot_idex = %d"), slot_index);
698
699 selfIPv6AddrValid =
700 (tANI_U8 *)vos_mem_malloc(sizeof(tANI_U8) * slot_index);
701
702 if (NULL == selfIPv6AddrValid)
703 {
704 hddLog (VOS_TRACE_LEVEL_ERROR, FL("Failed to allocate memory for"
705 " selfIPv6AddrValid"));
706 goto end;
707 }
708
709 vos_mem_zero(selfIPv6AddrValid, slot_index * sizeof(tANI_U8));
710
711 selfIPv6Addr = (tANI_U8 **)vos_mem_malloc(sizeof(tANI_U8 *) * slot_index);
712
713 if (NULL == selfIPv6Addr)
714 {
715 hddLog (VOS_TRACE_LEVEL_ERROR, FL("Failed to allocate memory for"
716 " selfIPv6Addr"));
717 goto end;
718 }
719
720 vos_mem_zero(selfIPv6Addr, slot_index * sizeof(tANI_U8 *));
721
722 for (slot = 0; slot < slot_index; slot++)
723 {
724 selfIPv6Addr[slot] =
725 (tANI_U8 *)vos_mem_malloc(SIR_MAC_IPV6_ADDR_LEN);
726 if (NULL == selfIPv6Addr[slot])
727 {
728 hddLog (VOS_TRACE_LEVEL_ERROR, FL("Failed to allocate memory"
729 "for selfIPv6Addr"));
730 goto end;
731 }
732 vos_mem_zero(selfIPv6Addr[slot], SIR_MAC_IPV6_ADDR_LEN);
733 }
734
735 i = 0;
736
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530737 if (fenable)
738 {
739 in6_dev = __in6_dev_get(pAdapter->dev);
740 if (NULL != in6_dev)
741 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530742 list_for_each(p, &in6_dev->addr_list)
743 {
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530744 if (i >= slot_index)
745 {
746 hddLog (VOS_TRACE_LEVEL_ERROR,
747 FL("IPv6 address list is greater than IPv6"
748 "address supported by firmware"));
749 hddLog (VOS_TRACE_LEVEL_ERROR,
750 FL("FW supported IPv6 address = %d"), slot_index);
751 break;
752 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530753 ifp = list_entry(p, struct inet6_ifaddr, if_list);
754 switch(ipv6_addr_src_scope(&ifp->addr))
755 {
756 case IPV6_ADDR_SCOPE_LINKLOCAL:
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530757 vos_mem_copy(selfIPv6Addr[i], &ifp->addr.s6_addr,
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530758 sizeof(ifp->addr.s6_addr));
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530759 selfIPv6AddrValid[i] = SIR_IPV6_ADDR_VALID;
Hardik Kantilal Patel1341bdf2013-08-22 20:27:15 +0530760 hddLog (VOS_TRACE_LEVEL_INFO,
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530761 FL("Found IPV6_ADDR_SCOPE_LINKLOCAL Address : %pI6"),
762 selfIPv6Addr[i]);
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530763 break;
764 case IPV6_ADDR_SCOPE_GLOBAL:
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530765 vos_mem_copy(selfIPv6Addr[i], &ifp->addr.s6_addr,
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530766 sizeof(ifp->addr.s6_addr));
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530767 selfIPv6AddrValid[i] = SIR_IPV6_ADDR_VALID;
Hardik Kantilal Patel1341bdf2013-08-22 20:27:15 +0530768 hddLog (VOS_TRACE_LEVEL_INFO,
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530769 FL("Found IPV6_ADDR_SCOPE_GLOBAL Address : %pI6"),
770 selfIPv6Addr[i]);
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530771 break;
772 default:
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530773 hddLog(VOS_TRACE_LEVEL_ERROR,
774 FL("The Scope %d is not supported"),
775 ipv6_addr_src_scope(&ifp->addr));
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530776 }
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530777 if (selfIPv6AddrValid[i] == SIR_IPV6_ADDR_VALID)
778 {
779 i++;
780 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530781 }
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530782
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530783 vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest));
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530784 for (i =0; i < slot_index; i++)
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530785 {
786 if (selfIPv6AddrValid[i])
787 {
788 //Filling up the request structure
789 /* Filling the selfIPv6Addr with solicited address
790 * A Solicited-Node multicast address is created by
791 * taking the last 24 bits of a unicast or anycast
792 * address and appending them to the prefix
793 *
794 * FF02:0000:0000:0000:0000:0001:FFXX:XX
795 *
796 * here XX is the unicast/anycast bits
797 */
798 offLoadRequest.nsOffloadInfo.selfIPv6Addr[0] = 0xFF;
799 offLoadRequest.nsOffloadInfo.selfIPv6Addr[1] = 0x02;
800 offLoadRequest.nsOffloadInfo.selfIPv6Addr[11] = 0x01;
801 offLoadRequest.nsOffloadInfo.selfIPv6Addr[12] = 0xFF;
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530802 offLoadRequest.nsOffloadInfo.selfIPv6Addr[13] =
803 selfIPv6Addr[i][13];
804 offLoadRequest.nsOffloadInfo.selfIPv6Addr[14] =
805 selfIPv6Addr[i][14];
806 offLoadRequest.nsOffloadInfo.selfIPv6Addr[15] =
807 selfIPv6Addr[i][15];
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530808 offLoadRequest.nsOffloadInfo.slotIdx = i;
809
810 vos_mem_copy(&offLoadRequest.nsOffloadInfo.targetIPv6Addr[0],
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530811 selfIPv6Addr[i], sizeof(tANI_U8)*SIR_MAC_IPV6_ADDR_LEN);
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530812 vos_mem_copy(&offLoadRequest.nsOffloadInfo.selfMacAddr,
813 &pAdapter->macAddressCurrent.bytes,
814 sizeof(tANI_U8)*SIR_MAC_ADDR_LEN);
815
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530816 offLoadRequest.nsOffloadInfo.targetIPv6AddrValid[0] =
817 SIR_IPV6_ADDR_VALID;
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530818 offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD;
819 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
820
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530821 hddLog (VOS_TRACE_LEVEL_INFO,
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530822 FL("configuredMcastBcastFilter: %d"
823 "NSOffload Slot = %d"),
824 pHddCtx->configuredMcastBcastFilter, i);
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530825
Kiet Lamc8e1eb52013-10-24 00:30:49 +0530826 if ((VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid)
827 && ((HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST ==
828 pHddCtx->sus_res_mcastbcast_filter) ||
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530829 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
Kiet Lamc8e1eb52013-10-24 00:30:49 +0530830 pHddCtx->sus_res_mcastbcast_filter)))
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530831 {
832 hddLog (VOS_TRACE_LEVEL_INFO,
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530833 FL("Set offLoadRequest with"
834 "SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE"));
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530835 offLoadRequest.enableOrDisable =
836 SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE;
837 }
838
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530839 vos_mem_copy(&offLoadRequest.params.hostIpv6Addr,
840 &offLoadRequest.nsOffloadInfo.targetIPv6Addr[0],
841 sizeof(tANI_U8)*SIR_MAC_IPV6_ADDR_LEN);
842
843 hddLog (VOS_TRACE_LEVEL_INFO,
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530844 FL("Setting NSOffload with solicitedIp: %pI6,"
845 "targetIp: %pI6"),
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530846 offLoadRequest.nsOffloadInfo.selfIPv6Addr,
847 offLoadRequest.nsOffloadInfo.targetIPv6Addr[0]);
848
849 //Configure the Firmware with this
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530850 returnStatus = sme_SetHostOffload(halHandle,
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530851 pAdapter->sessionId, &offLoadRequest);
852 if(eHAL_STATUS_SUCCESS != returnStatus)
853 {
854 hddLog(VOS_TRACE_LEVEL_ERROR,
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530855 FL("Failed to enable HostOffload feature with"
856 " status: %d"), returnStatus);
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530857 }
858 vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest));
859 }
860 }
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530861 if (fenable == 1 && !pAdapter->ipv6_notifier_registered)
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530862 {
863 // Register IPv6 notifier to notify if any change in IP
864 // So that we can reconfigure the offload parameters
865 pAdapter->ipv6_notifier.notifier_call =
866 wlan_hdd_ipv6_changed;
867 ret = register_inet6addr_notifier(&pAdapter->ipv6_notifier);
868 if (ret)
869 {
870 hddLog(LOGE, FL("Failed to register IPv6 notifier"));
871 }
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530872 else
873 {
874 hddLog(LOG1, FL("Registered IPv6 notifier"));
875 pAdapter->ipv6_notifier_registered = true;
876 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530877 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530878 }
879 else
880 {
881 hddLog(VOS_TRACE_LEVEL_ERROR,
882 FL("IPv6 dev does not exist. Failed to request NSOffload"));
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530883 goto end;
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530884 }
885 }
886 else
887 {
888 //Disable NSOffload
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530889 if (pAdapter->ipv6_notifier_registered)
890 {
891 hddLog(LOG1, FL("Unregistered IPv6 notifier"));
892 unregister_inet6addr_notifier(&pAdapter->ipv6_notifier);
893 pAdapter->ipv6_notifier_registered = false;
894 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530895 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
896 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
897 offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD;
898
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530899 for (i = 0; i < slot_index; i++)
Vinay Krishna Erannab29c6142014-01-07 12:20:51 +0530900 {
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530901 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Disable Slot= %d"), i);
Vinay Krishna Erannab29c6142014-01-07 12:20:51 +0530902 offLoadRequest.nsOffloadInfo.slotIdx = i;
903 if (eHAL_STATUS_SUCCESS !=
Vinay Krishna Eranna911a3b82014-01-07 12:20:51 +0530904 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
905 pAdapter->sessionId, &offLoadRequest))
Vinay Krishna Erannab29c6142014-01-07 12:20:51 +0530906 {
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530907 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failure to disable"
908 " %d Slot"), i);
Vinay Krishna Erannab29c6142014-01-07 12:20:51 +0530909 }
910 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530911 }
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530912end:
913 while (slot > 0 && selfIPv6Addr[--slot])
914 {
915 vos_mem_free(selfIPv6Addr[slot]);
916 }
917 if (selfIPv6Addr)
918 {
919 vos_mem_free(selfIPv6Addr);
920 }
921 if (selfIPv6AddrValid)
922 {
923 vos_mem_free(selfIPv6AddrValid);
924 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530925 return;
926}
927#endif
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530928
929void hdd_ipv4_notifier_work_queue(struct work_struct *work)
930{
931 hdd_adapter_t* pAdapter =
932 container_of(work, hdd_adapter_t, ipv4NotifierWorkQueue);
933 hdd_context_t *pHddCtx;
934 int status;
935
936 hddLog(LOG1, FL("Reconfiguring ARP Offload"));
937 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
938 status = wlan_hdd_validate_context(pHddCtx);
939 if (0 != status)
940 {
941 hddLog(LOGE, FL("HDD context is invalid"));
942 return;
943 }
944
Deepthi Gowri5933f402014-01-23 17:48:24 +0530945 if ( VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid)
946 {
947 pHddCtx->sus_res_mcastbcast_filter =
948 pHddCtx->configuredMcastBcastFilter;
949 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
950 }
951
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530952 if ((eConnectionState_Associated ==
953 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)
Deepthi Gowri5933f402014-01-23 17:48:24 +0530954 && (pHddCtx->hdd_wlan_suspended))
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530955 {
956 // This invocation being part of the IPv4 registration callback,
957 // we are passing second parameter as 2 to avoid registration
958 // of IPv4 notifier again.
959 hdd_conf_arp_offload(pAdapter, 2);
960 }
961}
962
963static int wlan_hdd_ipv4_changed(struct notifier_block *nb,
964 unsigned long data, void *arg)
965{
966 struct in_ifaddr *ifa = (struct in_ifaddr *)arg;
967 struct in_ifaddr **ifap = NULL;
968 struct in_device *in_dev;
969
970 struct net_device *ndev = ifa->ifa_dev->dev;
971 hdd_adapter_t *pAdapter =
972 container_of(nb, struct hdd_adapter_s, ipv4_notifier);
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +0530973 hdd_context_t *pHddCtx;
974 int status;
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530975 if (pAdapter && pAdapter->dev == ndev)
976 {
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +0530977 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
978 status = wlan_hdd_validate_context(pHddCtx);
979 if (0 != status)
980 {
981 hddLog(LOGE, FL("HDD context is invalid"));
982 return NOTIFY_DONE;
983 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530984 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
985 {
986 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
987 ifap = &ifa->ifa_next)
988 {
989 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
990 {
991 break; /* found */
992 }
993 }
994 }
995 if(ifa && ifa->ifa_local)
996 {
997 schedule_work(&pAdapter->ipv4NotifierWorkQueue);
998 }
999 }
1000
1001 return NOTIFY_DONE;
1002}
1003
1004/**----------------------------------------------------------------------------
1005
1006 \brief hdd_conf_arp_offload() - Configure ARP offload
1007
1008 Called during SUSPEND to configure the ARP offload (MC BC filter) which
1009 reduces power consumption.
1010
1011 \param - pAdapter -Adapter context for which ARP offload is to be configured
1012 \param - fenable - 0 - disable.
1013 1 - enable. (with IPv4 notifier registration)
1014 2 - enable. (without IPv4 notifier registration)
1015
1016 \return -
1017 VOS_STATUS_SUCCESS - on successful operation
1018 VOS_STATUS_E_FAILURE - on failure of operation
1019-----------------------------------------------------------------------------*/
1020VOS_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, int fenable)
Jeff Johnson295189b2012-06-20 16:38:30 -07001021{
1022 struct in_ifaddr **ifap = NULL;
1023 struct in_ifaddr *ifa = NULL;
1024 struct in_device *in_dev;
1025 int i = 0;
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301026 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001027 tSirHostOffloadReq offLoadRequest;
Yathish9f22e662012-12-10 14:21:35 -08001028 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001029
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301030 hddLog(VOS_TRACE_LEVEL_ERROR, FL(" fenable = %d \n"), fenable);
Jeff Johnson295189b2012-06-20 16:38:30 -07001031
Jeff Johnson295189b2012-06-20 16:38:30 -07001032 if(fenable)
1033 {
1034 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
1035 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301036 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001037 ifap = &ifa->ifa_next)
1038 {
1039 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
1040 {
1041 break; /* found */
1042 }
1043 }
1044 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001045 if(ifa && ifa->ifa_local)
1046 {
1047 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
1048 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
1049
Arif Hussain6d2a3322013-11-17 19:50:10 -08001050 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001051
Amar Singhald53568e2013-09-26 11:03:45 -07001052 if (((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
1053 pHddCtx->sus_res_mcastbcast_filter) ||
1054 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
1055 pHddCtx->sus_res_mcastbcast_filter)) &&
1056 (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid))
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -07001057 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301058 offLoadRequest.enableOrDisable =
Amar Singhald53568e2013-09-26 11:03:45 -07001059 SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
1060 hddLog(VOS_TRACE_LEVEL_INFO,
1061 "offload: inside arp offload conditional check");
Jeff Johnson295189b2012-06-20 16:38:30 -07001062 }
Amar Singhald53568e2013-09-26 11:03:45 -07001063
1064 hddLog(VOS_TRACE_LEVEL_INFO, "offload: arp filter programmed = %d",
1065 offLoadRequest.enableOrDisable);
1066
Jeff Johnson295189b2012-06-20 16:38:30 -07001067 //converting u32 to IPV4 address
1068 for(i = 0 ; i < 4; i++)
1069 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301070 offLoadRequest.params.hostIpv4Addr[i] =
Jeff Johnson295189b2012-06-20 16:38:30 -07001071 (ifa->ifa_local >> (i*8) ) & 0xFF ;
1072 }
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301073 hddLog(VOS_TRACE_LEVEL_INFO, " Enable SME HostOffload: %d.%d.%d.%d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001074 offLoadRequest.params.hostIpv4Addr[0],
1075 offLoadRequest.params.hostIpv4Addr[1],
1076 offLoadRequest.params.hostIpv4Addr[2],
1077 offLoadRequest.params.hostIpv4Addr[3]);
1078
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301079 if (eHAL_STATUS_SUCCESS !=
1080 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1081 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -07001082 {
1083 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to enable HostOffload "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001084 "feature", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001085 return VOS_STATUS_E_FAILURE;
1086 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001087 }
1088 else
1089 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05301090 hddLog(VOS_TRACE_LEVEL_ERROR, FL("IP Address is not assigned"));
1091 return VOS_STATUS_E_AGAIN;
Jeff Johnson295189b2012-06-20 16:38:30 -07001092 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301093
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05301094 if (fenable == 1 && !pAdapter->ipv4_notifier_registered)
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301095 {
1096 // Register IPv4 notifier to notify if any change in IP
1097 // So that we can reconfigure the offload parameters
1098 pAdapter->ipv4_notifier.notifier_call =
1099 wlan_hdd_ipv4_changed;
1100 ret = register_inetaddr_notifier(&pAdapter->ipv4_notifier);
1101 if (ret)
1102 {
1103 hddLog(LOGE, FL("Failed to register IPv4 notifier"));
1104 }
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05301105 else
1106 {
1107 hddLog(LOG1, FL("Registered IPv4 notifier"));
1108 pAdapter->ipv4_notifier_registered = true;
1109 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301110 }
1111 return VOS_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07001112 }
1113 else
1114 {
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05301115 if (pAdapter->ipv4_notifier_registered)
1116 {
1117 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
1118 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
1119 pAdapter->ipv4_notifier_registered = false;
1120 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001121 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
1122 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
1123 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
1124
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301125 if (eHAL_STATUS_SUCCESS !=
1126 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1127 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -07001128 {
1129 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to disable host "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001130 "offload feature", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001131 return VOS_STATUS_E_FAILURE;
1132 }
1133 return VOS_STATUS_SUCCESS;
1134 }
1135}
1136
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301137/*
1138 * This function is called before setting mcbc filters
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301139 * to modify filter value considering Different Offloads
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301140*/
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301141void hdd_mcbc_filter_modification(hdd_context_t* pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301142 tANI_U8 *pMcBcFilter)
1143{
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301144 if (NULL == pHddCtx)
1145 {
1146 hddLog(VOS_TRACE_LEVEL_ERROR, FL("NULL HDD context passed"));
1147 return;
1148 }
1149
1150 *pMcBcFilter = pHddCtx->configuredMcastBcastFilter;
1151 if (pHddCtx->cfg_ini->fhostArpOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301152 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301153 /* ARP offload is enabled, do not block bcast packets at RXP
1154 * Will be using Bitmasking to reset the filter. As we have
1155 * disable Broadcast filtering, Anding with the negation
1156 * of Broadcast BIT
1157 */
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301158 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301159 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301160
1161#ifdef WLAN_NS_OFFLOAD
1162 if (pHddCtx->cfg_ini->fhostNSOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301163 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301164 /* NS offload is enabled, do not block mcast packets at RXP
1165 * Will be using Bitmasking to reset the filter. As we have
1166 * disable Multicast filtering, Anding with the negation
1167 * of Multicast BIT
1168 */
1169 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301170 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301171#endif
1172
1173 pHddCtx->configuredMcastBcastFilter = *pMcBcFilter;
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301174}
1175
Jeff Johnson295189b2012-06-20 16:38:30 -07001176void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter)
1177{
1178 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001179 tpSirWlanSetRxpFilters wlanRxpFilterParam =
1180 vos_mem_malloc(sizeof(tSirWlanSetRxpFilters));
1181 if(NULL == wlanRxpFilterParam)
1182 {
1183 hddLog(VOS_TRACE_LEVEL_FATAL,
1184 "%s: vos_mem_alloc failed ", __func__);
1185 return;
1186 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001187 hddLog(VOS_TRACE_LEVEL_INFO,
1188 "%s: Configuring Mcast/Bcast Filter Setting. setfilter %d", __func__, setfilter);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301189 if (TRUE == setfilter)
1190 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301191 hdd_mcbc_filter_modification(pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301192 &wlanRxpFilterParam->configuredMcstBcstFilterSetting);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301193 }
1194 else
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301195 {
1196 /*Use the current configured value to clear*/
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301197 wlanRxpFilterParam->configuredMcstBcstFilterSetting =
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301198 pHddCtx->configuredMcastBcastFilter;
1199 }
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301200
Jeff Johnson295189b2012-06-20 16:38:30 -07001201 wlanRxpFilterParam->setMcstBcstFilter = setfilter;
Jeff Johnson295189b2012-06-20 16:38:30 -07001202 halStatus = sme_ConfigureRxpFilter(pHddCtx->hHal, wlanRxpFilterParam);
Chilam Ngc4244af2013-04-01 15:37:32 -07001203 if (eHAL_STATUS_SUCCESS != halStatus)
1204 vos_mem_free(wlanRxpFilterParam);
Jeff Johnson295189b2012-06-20 16:38:30 -07001205 if(setfilter && (eHAL_STATUS_SUCCESS == halStatus))
1206 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
1207}
1208
Jeff Johnson295189b2012-06-20 16:38:30 -07001209static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx,
1210 hdd_adapter_t *pAdapter)
1211{
1212 eHalStatus halStatus = eHAL_STATUS_FAILURE;
1213 tpSirWlanSuspendParam wlanSuspendParam =
1214 vos_mem_malloc(sizeof(tSirWlanSuspendParam));
1215
Amar Singhald53568e2013-09-26 11:03:45 -07001216 if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid) {
1217 pHddCtx->sus_res_mcastbcast_filter =
1218 pHddCtx->configuredMcastBcastFilter;
1219 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
1220 hddLog(VOS_TRACE_LEVEL_INFO, "offload: hdd_conf_suspend_ind");
1221 hddLog(VOS_TRACE_LEVEL_INFO, "configuredMCastBcastFilter saved = %d",
1222 pHddCtx->configuredMcastBcastFilter);
1223
1224 }
1225
Amar Singhal49fdfd52013-08-13 13:25:12 -07001226
Jeff Johnson295189b2012-06-20 16:38:30 -07001227 if(NULL == wlanSuspendParam)
1228 {
1229 hddLog(VOS_TRACE_LEVEL_FATAL,
1230 "%s: vos_mem_alloc failed ", __func__);
1231 return;
1232 }
1233
Amar Singhald53568e2013-09-26 11:03:45 -07001234 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001235 "%s: send wlan suspend indication", __func__);
1236
1237 if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER))
1238 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301239 //Configure supported OffLoads
1240 hdd_conf_hostoffload(pAdapter, TRUE);
1241 wlanSuspendParam->configuredMcstBcstFilterSetting = pHddCtx->configuredMcastBcastFilter;
Jeff Johnson295189b2012-06-20 16:38:30 -07001242
1243#ifdef WLAN_FEATURE_PACKET_FILTERING
madan mohan koyyalamudibfd9cef2013-07-01 18:39:37 +05301244 /* During suspend, configure MC Addr list filter to the firmware
1245 * function takes care of checking necessary conditions before
1246 * configuring.
1247 */
1248 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001249#endif
1250 }
1251
1252 halStatus = sme_ConfigureSuspendInd(pHddCtx->hHal, wlanSuspendParam);
1253 if(eHAL_STATUS_SUCCESS == halStatus)
1254 {
1255 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
Chilam Ngc4244af2013-04-01 15:37:32 -07001256 } else {
c_hpothuffdb5272013-10-02 16:42:35 +05301257 hddLog(VOS_TRACE_LEVEL_ERROR,
1258 FL("sme_ConfigureSuspendInd returned failure %d"), halStatus);
Chilam Ngc4244af2013-04-01 15:37:32 -07001259 vos_mem_free(wlanSuspendParam);
Jeff Johnson295189b2012-06-20 16:38:30 -07001260 }
1261}
1262
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301263static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001264{
Chilam Ngc4244af2013-04-01 15:37:32 -07001265 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Yathish9f22e662012-12-10 14:21:35 -08001266 hdd_context_t* pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Chilam Ngc4244af2013-04-01 15:37:32 -07001267 tpSirWlanResumeParam wlanResumeParam;
Jeff Johnson295189b2012-06-20 16:38:30 -07001268
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301269 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001270 "%s: send wlan resume indication", __func__);
1271
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301272 wlanResumeParam = vos_mem_malloc(sizeof(tSirWlanResumeParam));
1273
1274 if (NULL == wlanResumeParam)
Jeff Johnson295189b2012-06-20 16:38:30 -07001275 {
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301276 hddLog(VOS_TRACE_LEVEL_FATAL,
1277 "%s: memory allocation failed for wlanResumeParam ", __func__);
1278 return;
Jeff Johnson295189b2012-06-20 16:38:30 -07001279 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001280
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301281 //Disable supported OffLoads
1282 hdd_conf_hostoffload(pAdapter, FALSE);
1283
1284 wlanResumeParam->configuredMcstBcstFilterSetting =
1285 pHddCtx->configuredMcastBcastFilter;
1286 halStatus = sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam);
1287 if (eHAL_STATUS_SUCCESS != halStatus)
1288 {
c_hpothuffdb5272013-10-02 16:42:35 +05301289 hddLog(VOS_TRACE_LEVEL_ERROR,
1290 "%s: sme_ConfigureResumeReq return failure %d", __func__, halStatus);
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301291 vos_mem_free(wlanResumeParam);
1292 }
1293
1294 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
1295
Amar Singhalf8ba2b82013-12-02 12:54:38 -08001296 if (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid) {
1297 pHddCtx->configuredMcastBcastFilter =
1298 pHddCtx->sus_res_mcastbcast_filter;
1299 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_FALSE;
1300 }
Amar Singhald53568e2013-09-26 11:03:45 -07001301
1302 hddLog(VOS_TRACE_LEVEL_INFO,
1303 "offload: in hdd_conf_resume_ind, restoring configuredMcastBcastFilter");
1304 hddLog(VOS_TRACE_LEVEL_INFO, "configuredMcastBcastFilter = %d",
1305 pHddCtx->configuredMcastBcastFilter);
Amar Singhal49fdfd52013-08-13 13:25:12 -07001306
Chilam Ngc4244af2013-04-01 15:37:32 -07001307
madan mohan koyyalamudibfd9cef2013-07-01 18:39:37 +05301308#ifdef WLAN_FEATURE_PACKET_FILTERING
1309 /* Filer was applied during suspend inditication
1310 * clear it when we resume.
1311 */
1312 wlan_hdd_set_mc_addr_list(pAdapter, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001313#endif
1314}
Jeff Johnson295189b2012-06-20 16:38:30 -07001315
Jeff Johnson295189b2012-06-20 16:38:30 -07001316//Suspend routine registered with Android OS
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001317void hdd_suspend_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001318{
1319 hdd_context_t *pHddCtx = NULL;
1320 v_CONTEXT_t pVosContext = NULL;
1321
Jeff Johnson295189b2012-06-20 16:38:30 -07001322 VOS_STATUS status;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301323 hdd_adapter_t *pAdapter = NULL;
1324 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301325 bool hdd_enter_bmps = FALSE;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001326
Jeff Johnson295189b2012-06-20 16:38:30 -07001327 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__);
1328
1329 //Get the global VOSS context.
1330 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1331 if(!pVosContext) {
1332 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1333 return;
1334 }
1335
1336 //Get the HDD context.
1337 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1338
1339 if(!pHddCtx) {
1340 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1341 return;
1342 }
1343
1344 if (pHddCtx->isLogpInProgress) {
1345 hddLog(VOS_TRACE_LEVEL_ERROR,
1346 "%s: Ignore suspend wlan, LOGP in progress!", __func__);
1347 return;
1348 }
1349
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301350 hdd_set_pwrparams(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001351 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1352 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1353 {
1354 pAdapter = pAdapterNode->pAdapter;
1355 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001356 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001357 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
1358
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001359 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001360 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1361 pAdapterNode = pNext;
1362 continue;
1363 }
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301364 /* Avoid multiple enter/exit BMPS in this while loop using
1365 * hdd_enter_bmps flag
1366 */
1367 if (FALSE == hdd_enter_bmps && (BMPS == pmcGetPmcState(pHddCtx->hHal)))
1368 {
1369 hdd_enter_bmps = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001370
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301371 /* If device was already in BMPS, and dynamic DTIM is set,
1372 * exit(set the device to full power) and enter BMPS again
1373 * to reflect new DTIM value */
1374 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
1375
1376 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
1377
1378 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1379 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001380#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1381 if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1382 {
1383 //stop the interface before putting the chip to standby
1384 netif_tx_disable(pAdapter->dev);
1385 netif_carrier_off(pAdapter->dev);
1386 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301387 else if (pHddCtx->cfg_ini->nEnableSuspend ==
Jeff Johnson295189b2012-06-20 16:38:30 -07001388 WLAN_MAP_SUSPEND_TO_DEEP_SLEEP)
1389 {
1390 //Execute deep sleep procedure
1391 hdd_enter_deep_sleep(pHddCtx, pAdapter);
1392 }
1393#endif
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301394
1395 /*Suspend notification sent down to driver*/
1396 hdd_conf_suspend_ind(pHddCtx, pAdapter);
1397
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301398 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1399 pAdapterNode = pNext;
1400 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301401 pHddCtx->hdd_wlan_suspended = TRUE;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301402
Jeff Johnson295189b2012-06-20 16:38:30 -07001403#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1404 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1405 {
1406 hdd_enter_standby(pHddCtx);
1407 }
1408#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001409
1410 return;
1411}
1412
1413static void hdd_PowerStateChangedCB
1414(
1415 v_PVOID_t callbackContext,
1416 tPmcState newState
1417)
1418{
1419 hdd_context_t *pHddCtx = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07001420 /* if the driver was not in BMPS during early suspend,
1421 * the dynamic DTIM is now updated at Riva */
1422 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended
1423 && pHddCtx->cfg_ini->enableDynamicDTIM
1424 && (pHddCtx->hdd_ignore_dtim_enabled == FALSE))
1425 {
1426 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1427 }
1428 spin_lock(&pHddCtx->filter_lock);
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301429 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended)
1430 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001431 spin_unlock(&pHddCtx->filter_lock);
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301432 if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid)
1433 {
Amar Singhald53568e2013-09-26 11:03:45 -07001434 pHddCtx->sus_res_mcastbcast_filter =
1435 pHddCtx->configuredMcastBcastFilter;
1436 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
1437
1438 hddLog(VOS_TRACE_LEVEL_INFO, "offload: callback to associated");
1439 hddLog(VOS_TRACE_LEVEL_INFO, "saving configuredMcastBcastFilter = %d",
1440 pHddCtx->configuredMcastBcastFilter);
1441 hddLog(VOS_TRACE_LEVEL_INFO,
1442 "offload: calling hdd_conf_mcastbcast_filter");
1443
1444 }
1445
Jeff Johnson295189b2012-06-20 16:38:30 -07001446 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001447 if(pHddCtx->hdd_mcastbcast_filter_set != TRUE)
1448 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__);
1449 }
Amar Singhal49fdfd52013-08-13 13:25:12 -07001450 else
Mihir Shete793209f2014-01-06 11:01:12 +05301451 {
1452 /* Android framework can send resume request when the WCN chip is
1453 * in IMPS mode. When the chip exits IMPS mode the firmware will
1454 * restore all the registers to the state they were before the chip
1455 * entered IMPS and so our hardware filter settings confgured by the
1456 * resume request will be lost. So reconfigure the filters on detecting
1457 * a change in the power state of the WCN chip.
1458 */
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301459 spin_unlock(&pHddCtx->filter_lock);
Mihir Shete793209f2014-01-06 11:01:12 +05301460 if (IMPS != newState)
1461 {
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301462 spin_lock(&pHddCtx->filter_lock);
Mihir Shete793209f2014-01-06 11:01:12 +05301463 if (FALSE == pHddCtx->hdd_wlan_suspended)
1464 {
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301465 spin_unlock(&pHddCtx->filter_lock);
Mihir Shete793209f2014-01-06 11:01:12 +05301466 hddLog(VOS_TRACE_LEVEL_INFO,
1467 "Not in IMPS/BMPS and suspended state");
1468 hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
1469 }
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301470 else
1471 {
1472 spin_unlock(&pHddCtx->filter_lock);
1473 }
Mihir Shete793209f2014-01-06 11:01:12 +05301474 }
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301475 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001476}
1477
1478
1479
1480void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx)
1481{
1482 v_CONTEXT_t pVosContext;
1483 tHalHandle smeContext;
1484
1485 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1486 if (NULL == pVosContext)
1487 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001488 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001489 return;
1490 }
1491 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1492 if (NULL == smeContext)
1493 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001494 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001495 return;
1496 }
1497
1498 spin_lock_init(&pHddCtx->filter_lock);
1499 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1500 pHddCtx->cfg_ini->nEnableSuspend)
1501 {
1502 pmcRegisterDeviceStateUpdateInd(smeContext,
1503 hdd_PowerStateChangedCB, pHddCtx);
1504 }
1505}
1506
1507void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx)
1508{
1509 v_CONTEXT_t pVosContext;
1510 tHalHandle smeContext;
1511
1512 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1513 if (NULL == pVosContext)
1514 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001515 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001516 return;
1517 }
1518 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1519 if (NULL == smeContext)
1520 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001521 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001522 return;
1523 }
1524
1525 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1526 pHddCtx->cfg_ini->nEnableSuspend)
1527 {
1528 pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB);
1529 }
1530}
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301531
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301532#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301533void hdd_conf_gtk_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301534{
1535 eHalStatus ret;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301536 tSirGtkOffloadParams hddGtkOffloadReqParams;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301537 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1538
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301539 if(fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301540 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301541 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1542 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags ))
1543 {
1544 vos_mem_copy(&hddGtkOffloadReqParams,
1545 &pHddStaCtx->gtkOffloadReqParams,
1546 sizeof (tSirGtkOffloadParams));
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301547
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301548 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1549 &hddGtkOffloadReqParams, pAdapter->sessionId);
1550 if (eHAL_STATUS_SUCCESS != ret)
1551 {
1552 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1553 "%s: sme_SetGTKOffload failed, returned %d",
1554 __func__, ret);
1555 return;
1556 }
1557
1558 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1559 "%s: sme_SetGTKOffload successfull", __func__);
1560 }
1561
1562 }
1563 else
1564 {
1565 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1566 (0 == memcmp(&pHddStaCtx->gtkOffloadReqParams.bssId,
1567 &pHddStaCtx->conn_info.bssId, WNI_CFG_BSSID_LEN)) &&
1568 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags))
1569 {
1570
1571 /* Host driver has previously offloaded GTK rekey */
1572 ret = sme_GetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301573 wlan_hdd_cfg80211_update_replayCounterCallback,
1574 pAdapter, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301575 if (eHAL_STATUS_SUCCESS != ret)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301576
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301577 {
1578 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1579 "%s: sme_GetGTKOffload failed, returned %d",
1580 __func__, ret);
1581 return;
1582 }
1583 else
1584 {
1585 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1586 "%s: sme_GetGTKOffload successful",
1587 __func__);
1588
1589 /* Sending GTK offload dissable */
1590 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
1591 sizeof (tSirGtkOffloadParams));
1592 hddGtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE;
1593 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301594 &hddGtkOffloadReqParams, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301595 if (eHAL_STATUS_SUCCESS != ret)
1596 {
1597 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1598 "%s: failed to dissable GTK offload, returned %d",
1599 __func__, ret);
1600 return;
1601 }
1602 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1603 "%s: successfully dissabled GTK offload request to HAL",
1604 __func__);
1605 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301606 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301607 }
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301608 return;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301609}
1610#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
Jeff Johnson295189b2012-06-20 16:38:30 -07001611
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001612void hdd_resume_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001613{
1614 hdd_context_t *pHddCtx = NULL;
1615 hdd_adapter_t *pAdapter = NULL;
1616 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1617 VOS_STATUS status;
1618 v_CONTEXT_t pVosContext = NULL;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001619
Jeff Johnson295189b2012-06-20 16:38:30 -07001620 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
1621
1622 //Get the global VOSS context.
1623 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1624 if(!pVosContext) {
1625 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1626 return;
1627 }
1628
1629 //Get the HDD context.
1630 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1631
1632 if(!pHddCtx) {
1633 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1634 return;
1635 }
1636
Agarwal Ashish971c2882013-10-30 20:11:12 +05301637 if (pHddCtx->isLogpInProgress)
1638 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001639 hddLog(VOS_TRACE_LEVEL_INFO,
1640 "%s: Ignore resume wlan, LOGP in progress!", __func__);
1641 return;
1642 }
1643
Jeff Johnson295189b2012-06-20 16:38:30 -07001644 pHddCtx->hdd_wlan_suspended = FALSE;
1645 /*loop through all adapters. Concurrency */
1646 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1647
1648 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1649 {
1650 pAdapter = pAdapterNode->pAdapter;
1651 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001652 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001653 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001654 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001655 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1656 pAdapterNode = pNext;
1657 continue;
1658 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301659
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301660
Jeff Johnson295189b2012-06-20 16:38:30 -07001661#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1662 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP)
1663 {
1664 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__);
1665 hdd_exit_deep_sleep(pAdapter);
1666 }
1667#endif
1668
1669 if(pHddCtx->hdd_ignore_dtim_enabled == TRUE)
1670 {
1671 /*Switch back to DTIM 1*/
1672 tSirSetPowerParamsReq powerRequest = { 0 };
1673
1674 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
1675 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07001676 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001677
1678 /*Disabled ModulatedDTIM if enabled on suspend*/
1679 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1680 powerRequest.uDTIMPeriod = 0;
1681
1682 /* Update ignoreDTIM and ListedInterval in CFG with default values */
1683 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1684 NULL, eANI_BOOLEAN_FALSE);
1685 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1686 NULL, eANI_BOOLEAN_FALSE);
1687
1688 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001689 "Switch to DTIM%d",powerRequest.uListenInterval);
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08001690 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001691
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301692 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
1693 {
1694 /* put the device into full power */
1695 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001696
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301697 /* put the device back into BMPS */
1698 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
Jeff Johnson295189b2012-06-20 16:38:30 -07001699
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301700 pHddCtx->hdd_ignore_dtim_enabled = FALSE;
1701 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001702 }
1703
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301704 hdd_conf_resume_ind(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001705 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1706 pAdapterNode = pNext;
1707 }
1708
1709#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1710 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY)
1711 {
1712 hdd_exit_standby(pHddCtx);
1713 }
1714#endif
1715
Jeff Johnson295189b2012-06-20 16:38:30 -07001716 return;
1717}
1718
Jeff Johnson295189b2012-06-20 16:38:30 -07001719VOS_STATUS hdd_wlan_reset_initialization(void)
1720{
Jeff Johnson295189b2012-06-20 16:38:30 -07001721 v_CONTEXT_t pVosContext = NULL;
1722
1723 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1724
1725 //Get the global VOSS context.
1726 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1727 if(!pVosContext)
1728 {
1729 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1730 return VOS_STATUS_E_FAILURE;
1731 }
1732
1733 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__);
1734
1735 // Prevent the phone from going to sleep
1736 hdd_prevent_suspend();
1737
Jeff Johnson295189b2012-06-20 16:38:30 -07001738 return VOS_STATUS_SUCCESS;
1739}
1740
1741
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001742/*
1743 * Based on the ioctl command recieved by HDD, put WLAN driver
1744 * into the quiet mode. This is the same as the early suspend
1745 * notification that driver used to listen
1746 */
1747void hdd_set_wlan_suspend_mode(bool suspend)
Jeff Johnson295189b2012-06-20 16:38:30 -07001748{
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001749 if (suspend)
1750 hdd_suspend_wlan();
1751 else
1752 hdd_resume_wlan();
Jeff Johnson295189b2012-06-20 16:38:30 -07001753}
1754
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001755static void hdd_ssr_timer_init(void)
1756{
1757 init_timer(&ssr_timer);
1758}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001759
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001760static void hdd_ssr_timer_del(void)
1761{
1762 del_timer(&ssr_timer);
1763 ssr_timer_started = false;
1764}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001765
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001766static void hdd_ssr_timer_cb(unsigned long data)
1767{
1768 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD SSR timer expired", __func__);
Sameer Thalappile5637f42013-08-07 15:46:55 -07001769
1770#ifdef WCN_PRONTO
1771 if (wcnss_hardware_type() == WCNSS_PRONTO_HW)
1772 wcnss_pronto_log_debug_regs();
1773#endif
1774
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001775 VOS_BUG(0);
1776}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001777
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001778static void hdd_ssr_timer_start(int msec)
1779{
1780 if(ssr_timer_started)
1781 {
1782 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: trying to start SSR timer when it's running"
1783 ,__func__);
1784 }
1785 ssr_timer.expires = jiffies + msecs_to_jiffies(msec);
1786 ssr_timer.function = hdd_ssr_timer_cb;
1787 add_timer(&ssr_timer);
1788 ssr_timer_started = true;
1789}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001790
Jeff Johnson295189b2012-06-20 16:38:30 -07001791/* the HDD interface to WLAN driver shutdown,
1792 * the primary shutdown function in SSR
1793 */
1794VOS_STATUS hdd_wlan_shutdown(void)
1795{
1796 VOS_STATUS vosStatus;
1797 v_CONTEXT_t pVosContext = NULL;
1798 hdd_context_t *pHddCtx = NULL;
1799 pVosSchedContext vosSchedContext = NULL;
c_hpothuffdb5272013-10-02 16:42:35 +05301800 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07001801
1802 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__);
1803
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001804 /* if re-init never happens, then do SSR1 */
1805 hdd_ssr_timer_init();
1806 hdd_ssr_timer_start(HDD_SSR_BRING_UP_TIME);
1807
Jeff Johnson295189b2012-06-20 16:38:30 -07001808 /* Get the global VOSS context. */
1809 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1810 if(!pVosContext) {
1811 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1812 return VOS_STATUS_E_FAILURE;
1813 }
1814 /* Get the HDD context. */
1815 pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1816 if(!pHddCtx) {
1817 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1818 return VOS_STATUS_E_FAILURE;
1819 }
c_hpothud662a352013-12-26 15:09:12 +05301820
1821 //Stop the traffic monitor timer
1822 if ( VOS_TIMER_STATE_RUNNING ==
1823 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
1824 {
1825 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
1826 }
1827
Jeff Johnson295189b2012-06-20 16:38:30 -07001828 hdd_reset_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001829 /* DeRegister with platform driver as client for Suspend/Resume */
1830 vosStatus = hddDeregisterPmOps(pHddCtx);
1831 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1832 {
1833 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
1834 }
1835
1836 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
1837 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1838 {
1839 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
1840 }
1841
1842 /* Disable IMPS/BMPS as we do not want the device to enter any power
1843 * save mode on its own during reset sequence
1844 */
1845 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1846 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1847 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1848
1849 vosSchedContext = get_vos_sched_ctxt();
1850
1851 /* Wakeup all driver threads */
1852 if(TRUE == pHddCtx->isMcThreadSuspended){
1853 complete(&vosSchedContext->ResumeMcEvent);
1854 pHddCtx->isMcThreadSuspended= FALSE;
1855 }
1856 if(TRUE == pHddCtx->isTxThreadSuspended){
1857 complete(&vosSchedContext->ResumeTxEvent);
1858 pHddCtx->isTxThreadSuspended= FALSE;
1859 }
1860 if(TRUE == pHddCtx->isRxThreadSuspended){
1861 complete(&vosSchedContext->ResumeRxEvent);
1862 pHddCtx->isRxThreadSuspended= FALSE;
1863 }
1864 /* Reset the Suspend Variable */
1865 pHddCtx->isWlanSuspended = FALSE;
1866
1867 /* Stop all the threads; we do not want any messages to be a processed,
1868 * any more and the best way to ensure that is to terminate the threads
1869 * gracefully.
1870 */
1871 /* Wait for MC to exit */
1872 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
1873 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
1874 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
1875 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
c_hpothuffdb5272013-10-02 16:42:35 +05301876 ret = wait_for_completion_interruptible(&vosSchedContext->McShutdown);
1877 if (0 >= ret)
1878 {
1879 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:wait on McShutdown failed %ld",
1880 __func__, ret);
1881 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001882
1883 /* Wait for TX to exit */
1884 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
1885 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
1886 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
1887 wake_up_interruptible(&vosSchedContext->txWaitQueue);
c_hpothuffdb5272013-10-02 16:42:35 +05301888 ret = wait_for_completion_interruptible(&vosSchedContext->TxShutdown);
1889 if (0 >= ret)
1890 {
1891 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:wait on TxShutdown failed %ld",
1892 __func__, ret);
1893 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001894
1895 /* Wait for RX to exit */
1896 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
1897 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
1898 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
1899 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
c_hpothuffdb5272013-10-02 16:42:35 +05301900
1901 ret = wait_for_completion_interruptible(&vosSchedContext->RxShutdown);
1902 if (0 >= ret)
1903 {
1904 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:wait on RxShutdown failed %ld",
1905 __func__, ret);
1906 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001907
1908#ifdef WLAN_BTAMP_FEATURE
1909 vosStatus = WLANBAP_Stop(pVosContext);
1910 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1911 {
1912 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1913 "%s: Failed to stop BAP",__func__);
1914 }
1915#endif //WLAN_BTAMP_FEATURE
1916 vosStatus = vos_wda_shutdown(pVosContext);
c_hpothuffdb5272013-10-02 16:42:35 +05301917 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1918 {
1919 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1920 "%s: Failed to stop wda %d", __func__, vosStatus);
1921 VOS_ASSERT(0);
1922 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001923
1924 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
1925 /* Stop SME - Cannot invoke vos_stop as vos_stop relies
1926 * on threads being running to process the SYS Stop
1927 */
Kiet Lama72a2322013-11-15 11:18:11 +05301928 vosStatus = sme_Stop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
c_hpothuffdb5272013-10-02 16:42:35 +05301929 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1930 {
1931 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1932 "%s: Failed to stop sme %d", __func__, vosStatus);
1933 VOS_ASSERT(0);
1934 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001935
1936 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
1937 /* Stop MAC (PE and HAL) */
1938 vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
c_hpothuffdb5272013-10-02 16:42:35 +05301939 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1940 {
1941 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1942 "%s: Failed to stop mac %d", __func__, vosStatus);
1943 VOS_ASSERT(0);
1944 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001945
1946 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
1947 /* Stop TL */
1948 vosStatus = WLANTL_Stop(pVosContext);
c_hpothuffdb5272013-10-02 16:42:35 +05301949 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1950 {
1951 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1952 "%s: Failed to stop TL %d", __func__, vosStatus);
1953 VOS_ASSERT(0);
1954 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001955
Jeff Johnson295189b2012-06-20 16:38:30 -07001956 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001957 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__);
1958 /* Clean up message queues of TX and MC thread */
1959 vos_sched_flush_mc_mqs(vosSchedContext);
1960 vos_sched_flush_tx_mqs(vosSchedContext);
1961 vos_sched_flush_rx_mqs(vosSchedContext);
1962
1963 /* Deinit all the TX and MC queues */
1964 vos_sched_deinit_mqs(vosSchedContext);
1965 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__);
1966
1967 /* shutdown VOSS */
1968 vos_shutdown(pVosContext);
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05301969
1970 /*mac context has already been released in mac_close call
1971 so setting it to NULL in hdd context*/
1972 pHddCtx->hHal = (tHalHandle)NULL;
1973
Jeff Johnson295189b2012-06-20 16:38:30 -07001974 if (free_riva_power_on_lock("wlan"))
1975 {
1976 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
1977 __func__);
1978 }
1979 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete"
1980 ,__func__);
1981 return VOS_STATUS_SUCCESS;
1982}
1983
1984
1985
1986/* the HDD interface to WLAN driver re-init.
1987 * This is called to initialize/start WLAN driver after a shutdown.
1988 */
1989VOS_STATUS hdd_wlan_re_init(void)
1990{
1991 VOS_STATUS vosStatus;
1992 v_CONTEXT_t pVosContext = NULL;
1993 hdd_context_t *pHddCtx = NULL;
1994 eHalStatus halStatus;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07001995#ifdef HAVE_WCNSS_CAL_DOWNLOAD
1996 int max_retries = 0;
1997#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001998#ifdef WLAN_BTAMP_FEATURE
1999 hdd_config_t *pConfig = NULL;
2000 WLANBAP_ConfigType btAmpConfig;
2001#endif
2002
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07002003 hdd_ssr_timer_del();
Jeff Johnson295189b2012-06-20 16:38:30 -07002004 hdd_prevent_suspend();
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08002005
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07002006#ifdef HAVE_WCNSS_CAL_DOWNLOAD
2007 /* wait until WCNSS driver downloads NV */
2008 while (!wcnss_device_ready() && 5 >= ++max_retries) {
2009 msleep(1000);
2010 }
2011 if (max_retries >= 5) {
2012 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
2013 goto err_re_init;
2014 }
2015#endif
2016
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07002017 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, TRUE);
2018
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08002019 /* The driver should always be initialized in STA mode after SSR */
2020 hdd_set_conparam(0);
2021
Jeff Johnson295189b2012-06-20 16:38:30 -07002022 /* Re-open VOSS, it is a re-open b'se control transport was never closed. */
2023 vosStatus = vos_open(&pVosContext, 0);
2024 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2025 {
2026 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
2027 goto err_re_init;
2028 }
2029
2030 /* Get the HDD context. */
2031 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
2032 if(!pHddCtx)
2033 {
2034 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
2035 goto err_vosclose;
2036 }
2037
2038 /* Save the hal context in Adapter */
2039 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
2040 if ( NULL == pHddCtx->hHal )
2041 {
2042 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
2043 goto err_vosclose;
2044 }
2045
2046 /* Set the SME configuration parameters. */
2047 vosStatus = hdd_set_sme_config(pHddCtx);
2048 if ( VOS_STATUS_SUCCESS != vosStatus )
2049 {
2050 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
2051 goto err_vosclose;
2052 }
2053
2054 /* Initialize the WMM module */
2055 vosStatus = hdd_wmm_init(pHddCtx);
2056 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
2057 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002058 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002059 goto err_vosclose;
2060 }
2061
2062 vosStatus = vos_preStart( pHddCtx->pvosContext );
2063 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2064 {
2065 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
2066 goto err_vosclose;
2067 }
2068
2069 /* In the integrated architecture we update the configuration from
2070 the INI file and from NV before vOSS has been started so that
2071 the final contents are available to send down to the cCPU */
2072 /* Apply the cfg.ini to cfg.dat */
2073 if (FALSE == hdd_update_config_dat(pHddCtx))
2074 {
2075 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
2076 goto err_vosclose;
2077 }
2078
2079 /* Set the MAC Address, currently this is used by HAL to add self sta.
2080 * Remove this once self sta is added as part of session open. */
2081 halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID,
2082 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
2083 sizeof(pHddCtx->cfg_ini->intfMacAddr[0]));
2084 if (!HAL_STATUS_SUCCESS(halStatus))
2085 {
2086 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
2087 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus);
2088 goto err_vosclose;
2089 }
2090
2091 /* Start VOSS which starts up the SME/MAC/HAL modules and everything else
2092 Note: Firmware image will be read and downloaded inside vos_start API */
2093 vosStatus = vos_start( pVosContext );
2094 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2095 {
2096 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
2097 goto err_vosclose;
2098 }
2099
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07002100 /* Exchange capability info between Host and FW and also get versioning info from FW */
2101 hdd_exchange_version_and_caps(pHddCtx);
2102
Jeff Johnson295189b2012-06-20 16:38:30 -07002103 vosStatus = hdd_post_voss_start_config( pHddCtx );
2104 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2105 {
2106 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
2107 __func__);
2108 goto err_vosstop;
2109 }
2110
2111#ifdef WLAN_BTAMP_FEATURE
2112 vosStatus = WLANBAP_Open(pVosContext);
2113 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
2114 {
2115 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2116 "%s: Failed to open BAP",__func__);
2117 goto err_vosstop;
2118 }
2119 vosStatus = BSL_Init(pVosContext);
2120 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
2121 {
2122 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2123 "%s: Failed to Init BSL",__func__);
2124 goto err_bap_close;
2125 }
2126 vosStatus = WLANBAP_Start(pVosContext);
2127 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2128 {
2129 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2130 "%s: Failed to start TL",__func__);
2131 goto err_bap_close;
2132 }
2133 pConfig = pHddCtx->cfg_ini;
2134 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
2135 vosStatus = WLANBAP_SetConfig(&btAmpConfig);
2136#endif //WLAN_BTAMP_FEATURE
2137
2138 /* Restart all adapters */
2139 hdd_start_all_adapters(pHddCtx);
2140 pHddCtx->isLogpInProgress = FALSE;
Sameer Thalappilb511beb2013-09-09 17:11:51 -07002141 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07002142 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002143 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002144
2145 /* Register with platform driver as client for Suspend/Resume */
2146 vosStatus = hddRegisterPmOps(pHddCtx);
2147 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2148 {
2149 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
2150 goto err_bap_stop;
2151 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002152 /* Allow the phone to go to sleep */
2153 hdd_allow_suspend();
2154 /* register for riva power on lock */
2155 if (req_riva_power_on_lock("wlan"))
2156 {
2157 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
2158 __func__);
2159 goto err_unregister_pmops;
2160 }
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07002161 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07002162 goto success;
2163
2164err_unregister_pmops:
2165 hddDeregisterPmOps(pHddCtx);
2166
2167err_bap_stop:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002168#ifdef CONFIG_HAS_EARLYSUSPEND
2169 hdd_unregister_mcast_bcast_filter(pHddCtx);
2170#endif
2171 hdd_close_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002172#ifdef WLAN_BTAMP_FEATURE
Jeff Johnson32d95a32012-09-10 13:15:23 -07002173 WLANBAP_Stop(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07002174#endif
2175
2176#ifdef WLAN_BTAMP_FEATURE
2177err_bap_close:
2178 WLANBAP_Close(pVosContext);
2179#endif
2180
2181err_vosstop:
2182 vos_stop(pVosContext);
2183
2184err_vosclose:
2185 vos_close(pVosContext);
2186 vos_sched_close(pVosContext);
2187 if (pHddCtx)
2188 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002189 /* Unregister the Net Device Notifier */
2190 unregister_netdevice_notifier(&hdd_netdev_notifier);
2191 /* Clean up HDD Nlink Service */
2192 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07002193#ifdef WLAN_KD_READY_NOTIFIER
2194 nl_srv_exit(pHddCtx->ptt_pid);
2195#else
Jeff Johnson295189b2012-06-20 16:38:30 -07002196 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07002197#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07002198 /* Free up dynamically allocated members inside HDD Adapter */
2199 kfree(pHddCtx->cfg_ini);
2200 pHddCtx->cfg_ini= NULL;
2201
Jeff Johnson295189b2012-06-20 16:38:30 -07002202 wiphy_unregister(pHddCtx->wiphy);
2203 wiphy_free(pHddCtx->wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07002204 }
2205 vos_preClose(&pVosContext);
2206
2207#ifdef MEMORY_DEBUG
2208 vos_mem_exit();
2209#endif
2210
2211err_re_init:
2212 /* Allow the phone to go to sleep */
2213 hdd_allow_suspend();
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07002214 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07002215 VOS_BUG(0);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002216 return -EPERM;
Jeff Johnson295189b2012-06-20 16:38:30 -07002217
2218success:
2219 /* Trigger replay of BTC events */
2220 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
2221 return VOS_STATUS_SUCCESS;
2222}