blob: db944444163dc01217ab4241bcf4de84301758dc [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Mukul Sharmabb94ece2014-04-04 21:22:15 +05302 * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
Kiet Lam842dad02014-02-18 18:44:02 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080020 */
Kiet Lam842dad02014-02-18 18:44:02 -080021
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
Jeff Johnson295189b2012-06-20 16:38:30 -070028/**=============================================================================
29* wlan_hdd_early_suspend.c
30*
31* \brief power management functions
32*
33* Description
34* Copyright 2009 (c) Qualcomm, Incorporated.
35* All Rights Reserved.
36* Qualcomm Confidential and Proprietary.
37*
38==============================================================================**/
39/* $HEADER$ */
40
41/**-----------------------------------------------------------------------------
42* Include files
43* ----------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -070044
45#include <linux/pm.h>
46#include <linux/wait.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070047#include <wlan_hdd_includes.h>
48#include <wlan_qct_driver.h>
49#include <linux/wakelock.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070050
51#include "halTypes.h"
52#include "sme_Api.h"
53#include <vos_api.h>
54#include "vos_power.h"
55#include <vos_sched.h>
56#include <macInitApi.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070057#include <wlan_qct_sys.h>
58#include <wlan_btc_svc.h>
59#include <wlan_nlink_common.h>
60#include <wlan_hdd_main.h>
61#include <wlan_hdd_assoc.h>
62#include <wlan_hdd_dev_pwr.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070063#include <wlan_nlink_srv.h>
64#include <wlan_hdd_misc.h>
Amar Singhald08ce752014-03-21 16:28:27 -070065#include "wlan_qct_wda.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070066
Jeff Johnson295189b2012-06-20 16:38:30 -070067#include <linux/semaphore.h>
68#include <wlan_hdd_hostapd.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070069#include "cfgApi.h"
70
71#ifdef WLAN_BTAMP_FEATURE
72#include "bapApi.h"
73#include "bap_hdd_main.h"
74#include "bap_hdd_misc.h"
75#endif
76
Jeff Johnsone7245742012-09-05 17:12:55 -070077#include <linux/wcnss_wlan.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070078#include <linux/inetdevice.h>
79#include <wlan_hdd_cfg.h>
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053080#include <wlan_hdd_cfg80211.h>
Gopichand Nakkala746a9452013-06-11 12:45:54 +053081#include <net/addrconf.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070082/**-----------------------------------------------------------------------------
83* Preprocessor definitions and constants
84* ----------------------------------------------------------------------------*/
85
86/**-----------------------------------------------------------------------------
87* Type declarations
88* ----------------------------------------------------------------------------*/
89
90/**-----------------------------------------------------------------------------
91* Function and variables declarations
92* ----------------------------------------------------------------------------*/
93#include "wlan_hdd_power.h"
94#include "wlan_hdd_packet_filtering.h"
95
Sameer Thalappile5637f42013-08-07 15:46:55 -070096#define HDD_SSR_BRING_UP_TIME 180000
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +053097#define NS_DEFAULT_SLOT_INDEX 4
98#define NS_EXTENDED_SLOT_INDEX 18
Jeff Johnson295189b2012-06-20 16:38:30 -070099
100static eHalStatus g_full_pwr_status;
101static eHalStatus g_standby_status;
102
103extern VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx);
104extern VOS_STATUS vos_chipExitDeepSleepVREGHandler(
105 vos_call_status_type* status,
106 vos_power_cb_type callback,
107 v_PVOID_t user_data);
108extern void hdd_wlan_initial_scan(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700109
110extern struct notifier_block hdd_netdev_notifier;
Jeff Johnson295189b2012-06-20 16:38:30 -0700111extern tVOS_CON_MODE hdd_get_conparam ( void );
Jeff Johnson295189b2012-06-20 16:38:30 -0700112
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -0700113static struct timer_list ssr_timer;
114static bool ssr_timer_started;
Jeff Johnson295189b2012-06-20 16:38:30 -0700115
116//Callback invoked by PMC to report status of standby request
117void hdd_suspend_standby_cbk (void *callbackContext, eHalStatus status)
118{
119 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
120 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Standby status = %d", __func__, status);
121 g_standby_status = status;
122
123 if(eHAL_STATUS_SUCCESS == status)
124 {
125 pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY;
126 }
127 else
128 {
129 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__);
130 }
131
132 complete(&pHddCtx->standby_comp_var);
133}
134
135//Callback invoked by PMC to report status of full power request
136void hdd_suspend_full_pwr_callback(void *callbackContext, eHalStatus status)
137{
138 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
139 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Full Power status = %d", __func__, status);
140 g_full_pwr_status = status;
141
142 if(eHAL_STATUS_SUCCESS == status)
143 {
144 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
145 }
146 else
147 {
148 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
149 }
150
151 complete(&pHddCtx->full_pwr_comp_var);
152}
153
154eHalStatus hdd_exit_standby(hdd_context_t *pHddCtx)
155{
156 eHalStatus status = VOS_STATUS_SUCCESS;
c_hpothuffdb5272013-10-02 16:42:35 +0530157 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -0700158
159 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from standby",__func__);
160 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
161
162 g_full_pwr_status = eHAL_STATUS_FAILURE;
163 status = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback, pHddCtx,
164 eSME_FULL_PWR_NEEDED_BY_HDD);
165
166 if(status == eHAL_STATUS_PMC_PENDING)
167 {
168 //Block on a completion variable. Can't wait forever though
c_hpothuffdb5272013-10-02 16:42:35 +0530169 ret = wait_for_completion_interruptible_timeout(
170 &pHddCtx->full_pwr_comp_var,
171 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
172 if (0 >= ret)
173 {
174 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:wait on full_pwr_comp_var failed %ld",
175 __func__, ret);
176 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700177 status = g_full_pwr_status;
178 if(g_full_pwr_status != eHAL_STATUS_SUCCESS)
179 {
180 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
181 VOS_ASSERT(0);
182 goto failure;
183 }
184 }
185 else if(status != eHAL_STATUS_SUCCESS)
186 {
187 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d",
188 __func__, status);
189 VOS_ASSERT(0);
190 goto failure;
191 }
192 else
193 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
194
195failure:
196 //No blocking to reduce latency. No other device should be depending on WLAN
197 //to finish resume and WLAN won't be instantly on after resume
198 return status;
199}
200
201
202//Helper routine to put the chip into standby
203VOS_STATUS hdd_enter_standby(hdd_context_t *pHddCtx)
204{
205 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
206 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
c_hpothuffdb5272013-10-02 16:42:35 +0530207 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -0700208
209 //Disable IMPS/BMPS as we do not want the device to enter any power
210 //save mode on its own during suspend sequence
211 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
212 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
213
214 //Note we do not disable queues unnecessarily. Queues should already be disabled
215 //if STA is disconnected or the queue will be disabled as and when disconnect
216 //happens because of standby procedure.
217
218 //Ensure that device is in full power first. There is scope for optimization
219 //here especially in scenarios where PMC is already in IMPS or REQUEST_IMPS.
220 //Core s/w needs to be optimized to handle this. Until then we request full
221 //power before issuing request for standby.
222 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
223 g_full_pwr_status = eHAL_STATUS_FAILURE;
224 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback,
225 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
226
227 if(halStatus == eHAL_STATUS_PMC_PENDING)
228 {
229 //Block on a completion variable. Can't wait forever though
c_hpothuffdb5272013-10-02 16:42:35 +0530230 ret = wait_for_completion_interruptible_timeout(
231 &pHddCtx->full_pwr_comp_var,
232 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
233 if (0 >= ret)
234 {
235 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:wait on full_pwr_comp_var failed %ld",
236 __func__, ret);
237 }
238
Jeff Johnson295189b2012-06-20 16:38:30 -0700239 if(g_full_pwr_status != eHAL_STATUS_SUCCESS)
240 {
241 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower Failed",__func__);
242 VOS_ASSERT(0);
243 vosStatus = VOS_STATUS_E_FAILURE;
244 goto failure;
245 }
246 }
247 else if(halStatus != eHAL_STATUS_SUCCESS)
248 {
249 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d",
250 __func__, halStatus);
251 VOS_ASSERT(0);
252 vosStatus = VOS_STATUS_E_FAILURE;
253 goto failure;
254 }
255
256 if(pHddCtx->hdd_mcastbcast_filter_set == TRUE) {
257 hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
258 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
259 }
260
261 //Request standby. Standby will cause the STA to disassociate first. TX queues
262 //will be disabled (by HDD) when STA disconnects. You do not want to disable TX
263 //queues here. Also do not assert if the failure code is eHAL_STATUS_PMC_NOT_NOW as PMC
264 //will send this failure code in case of concurrent sessions. Power Save cannot be supported
265 //when there are concurrent sessions.
266 INIT_COMPLETION(pHddCtx->standby_comp_var);
267 g_standby_status = eHAL_STATUS_FAILURE;
268 halStatus = sme_RequestStandby(pHddCtx->hHal, hdd_suspend_standby_cbk, pHddCtx);
269
270 if (halStatus == eHAL_STATUS_PMC_PENDING)
271 {
272 //Wait till WLAN device enters standby mode
c_hpothuffdb5272013-10-02 16:42:35 +0530273 ret = wait_for_completion_timeout(&pHddCtx->standby_comp_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700274 msecs_to_jiffies(WLAN_WAIT_TIME_STANDBY));
c_hpothuffdb5272013-10-02 16:42:35 +0530275 if (0 >= ret)
276 {
277 hddLog(VOS_TRACE_LEVEL_ERROR,
278 FL("wait on standby_comp_var failed %ld"), ret);
279 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700280 if (g_standby_status != eHAL_STATUS_SUCCESS && g_standby_status != eHAL_STATUS_PMC_NOT_NOW)
281 {
282 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__);
283 VOS_ASSERT(0);
284 vosStatus = VOS_STATUS_E_FAILURE;
285 goto failure;
286 }
287 }
288 else if (halStatus != eHAL_STATUS_SUCCESS && halStatus != eHAL_STATUS_PMC_NOT_NOW) {
289 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed - status %d",
290 __func__, halStatus);
291 VOS_ASSERT(0);
292 vosStatus = VOS_STATUS_E_FAILURE;
293 goto failure;
294 }
295 else
296 pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY;
297
298failure:
299 //Restore IMPS config
300 if(pHddCtx->cfg_ini->fIsImpsEnabled)
301 sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
302
303 //Restore BMPS config
304 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
305 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
306
307 return vosStatus;
308}
309
310
311//Helper routine for Deep sleep entry
312VOS_STATUS hdd_enter_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter)
313{
314 eHalStatus halStatus;
315 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
316 vos_call_status_type callType;
c_hpothuffdb5272013-10-02 16:42:35 +0530317 long ret;
Jeff Johnsonbc676b42013-02-14 16:04:08 -0800318
Jeff Johnson295189b2012-06-20 16:38:30 -0700319 //Stop the Interface TX queue.
320 netif_tx_disable(pAdapter->dev);
321 netif_carrier_off(pAdapter->dev);
322
323 //Disable IMPS,BMPS as we do not want the device to enter any power
324 //save mode on it own during suspend sequence
325 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
326 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
327
328 //Ensure that device is in full power as we will touch H/W during vos_Stop
329 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
330 g_full_pwr_status = eHAL_STATUS_FAILURE;
331 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback,
332 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
333
334 if(halStatus == eHAL_STATUS_PMC_PENDING)
335 {
336 //Block on a completion variable. Can't wait forever though
c_hpothuffdb5272013-10-02 16:42:35 +0530337 ret = wait_for_completion_interruptible_timeout(
338 &pHddCtx->full_pwr_comp_var,
339 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
340 if (0 >= ret)
341 {
342 hddLog(VOS_TRACE_LEVEL_ERROR,
343 FL("wait on full_pwr_comp_var failed %ld"), ret);
344 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700345 if(g_full_pwr_status != eHAL_STATUS_SUCCESS){
346 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
347 VOS_ASSERT(0);
348 }
349 }
350 else if(halStatus != eHAL_STATUS_SUCCESS)
351 {
352 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Request for Full Power failed",__func__);
353 VOS_ASSERT(0);
354 }
355
356 //Issue a disconnect. This is required to inform the supplicant that
357 //STA is getting disassociated and for GUI to be updated properly
358 INIT_COMPLETION(pAdapter->disconnect_comp_var);
359 halStatus = sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED);
360
361 //Success implies disconnect command got queued up successfully
362 if(halStatus == eHAL_STATUS_SUCCESS)
363 {
364 //Block on a completion variable. Can't wait forever though.
c_hpothuffdb5272013-10-02 16:42:35 +0530365 ret = wait_for_completion_interruptible_timeout(
366 &pAdapter->disconnect_comp_var,
367 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
368 if (0 >= ret)
369 {
370 hddLog(VOS_TRACE_LEVEL_ERROR,
371 FL("wait on disconnect_comp_var failed %ld"), ret);
372 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700373 }
374
375
376 //None of the steps should fail after this. Continue even in case of failure
377 vosStatus = vos_stop( pHddCtx->pvosContext );
c_hpothuffdb5272013-10-02 16:42:35 +0530378 if( !VOS_IS_STATUS_SUCCESS( vosStatus ))
379 {
380 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: vos_stop return failed %d",
381 __func__, vosStatus);
382 VOS_ASSERT(0);
383 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700384
Jeff Johnson295189b2012-06-20 16:38:30 -0700385 vosStatus = vos_chipAssertDeepSleep( &callType, NULL, NULL );
c_hpothuffdb5272013-10-02 16:42:35 +0530386 if( VOS_IS_STATUS_SUCCESS( vosStatus ))
387 {
388 hddLog(VOS_TRACE_LEVEL_ERROR,
389 FL("vos_chipAssertDeepSleep return failed %d"), vosStatus);
390 VOS_ASSERT(0);
391 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700392
393 //Vote off any PMIC voltage supplies
394 vosStatus = vos_chipPowerDown(NULL, NULL, NULL);
c_hpothuffdb5272013-10-02 16:42:35 +0530395 if( !VOS_IS_STATUS_SUCCESS( vosStatus ))
396 {
397 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: vos_chipPowerDown return failed %d",
398 __func__, vosStatus);
399 VOS_ASSERT(0);
400 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700401
Jeff Johnson295189b2012-06-20 16:38:30 -0700402 pHddCtx->hdd_ps_state = eHDD_SUSPEND_DEEP_SLEEP;
403
404 //Restore IMPS config
405 if(pHddCtx->cfg_ini->fIsImpsEnabled)
406 sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
407
408 //Restore BMPS config
409 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
410 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
411
Jeff Johnson295189b2012-06-20 16:38:30 -0700412 return vosStatus;
413}
414
415VOS_STATUS hdd_exit_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter)
416{
417 VOS_STATUS vosStatus;
418 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -0700419
420 //Power Up Libra WLAN card first if not already powered up
421 vosStatus = vos_chipPowerUp(NULL,NULL,NULL);
422 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
423 {
c_hpothuffdb5272013-10-02 16:42:35 +0530424 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN not Powered Up."
Jeff Johnson295189b2012-06-20 16:38:30 -0700425 "exiting", __func__);
426 goto err_deep_sleep;
427 }
428
Jeff Johnson295189b2012-06-20 16:38:30 -0700429 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
430 "%s: calling hdd_set_sme_config",__func__);
431 vosStatus = hdd_set_sme_config( pHddCtx );
432 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
433 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
434 {
435 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
436 "%s: Failed in hdd_set_sme_config",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700437 goto err_deep_sleep;
Jeff Johnson295189b2012-06-20 16:38:30 -0700438 }
439
440 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
441 "%s: calling vos_start",__func__);
442 vosStatus = vos_start( pHddCtx->pvosContext );
443 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
444 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
445 {
446 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
447 "%s: Failed in vos_start",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700448 goto err_deep_sleep;
Jeff Johnson295189b2012-06-20 16:38:30 -0700449 }
450
451 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
452 "%s: calling hdd_post_voss_start_config",__func__);
453 vosStatus = hdd_post_voss_start_config( pHddCtx );
454 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
455 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
456 {
457 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
458 "%s: Failed in hdd_post_voss_start_config",__func__);
459 goto err_voss_stop;
460 }
461
462
463 //Open a SME session for future operation
464 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pHddCtx,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -0700465 (tANI_U8 *)&pAdapter->macAddressCurrent,
466 &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700467 if ( !HAL_STATUS_SUCCESS( halStatus ) )
468 {
Jeff Johnson0299d0a2013-10-30 12:37:43 -0700469 hddLog(VOS_TRACE_LEVEL_FATAL,"sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -0700470 halStatus, halStatus );
471 goto err_voss_stop;
472
473 }
474
475 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
476
477 //Trigger the initial scan
478 hdd_wlan_initial_scan(pHddCtx);
479
480 return VOS_STATUS_SUCCESS;
481
482err_voss_stop:
483 vos_stop(pHddCtx->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -0700484err_deep_sleep:
485 return VOS_STATUS_E_FAILURE;
486
487}
488
Atul Mittal37385d72014-03-27 18:15:03 +0530489void hdd_ipv6_notifier_work_queue(struct work_struct *work)
490{
491 hdd_adapter_t* pAdapter =
492 container_of(work, hdd_adapter_t, ipv6NotifierWorkQueue);
493 hdd_context_t *pHddCtx;
494 int status;
495
496 hddLog(LOG1, FL("Reconfiguring NS Offload"));
497
498 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
499 status = wlan_hdd_validate_context(pHddCtx);
500 if (0 != status)
501 {
502 hddLog(LOGE, FL("HDD context is invalid"));
503 return;
504 }
505
506 if ( VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid)
507 {
508 pHddCtx->sus_res_mcastbcast_filter =
509 pHddCtx->configuredMcastBcastFilter;
Sushant Kaushik439d4c72014-05-12 16:39:51 +0530510 hddLog(LOG1, FL("saving configuredMcastBcastFilter = %d"),
511 pHddCtx->sus_res_mcastbcast_filter);
Atul Mittal37385d72014-03-27 18:15:03 +0530512 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
513 }
514
515 if ((eConnectionState_Associated ==
516 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)
517 && (pHddCtx->hdd_wlan_suspended))
518 {
519 // This invocation being part of the IPv6 registration callback,
520 // set the newly generated ip address to f/w in suspend mode.
521#ifdef WLAN_NS_OFFLOAD
522 //Disable NSOFFLOAD
523 if (pHddCtx->cfg_ini->fhostNSOffload)
524 {
525 hdd_conf_ns_offload(pAdapter, 1);
526 }
527#endif
528 }
529#ifdef WLAN_FEATURE_PACKET_FILTERING
530 /* wlan_hdd_set_mc_addr_list() is called from the early susspend
531 * only so when new ipv6 address is generated the screen may not
532 * on so we need to call it here to update the list in f/w.
533 */
534 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
535#endif
536
537}
538
539
540static int wlan_hdd_ipv6_changed(struct notifier_block *nb,
541 unsigned long data, void *arg)
542{
543 struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)arg;
544 struct net_device *ndev = ifa->idev->dev;
545 hdd_adapter_t *pAdapter =
546 container_of(nb, struct hdd_adapter_s, ipv6_notifier);
547 hdd_context_t *pHddCtx;
548 int status;
549
550 if (pAdapter && pAdapter->dev == ndev)
551 {
552 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
553 status = wlan_hdd_validate_context(pHddCtx);
554 if (0 != status)
555 {
556 hddLog(LOGE, FL("HDD context is invalid"));
557 return NOTIFY_DONE;
558 }
559
560 schedule_work(&pAdapter->ipv6NotifierWorkQueue);
561 }
562
563 return NOTIFY_DONE;
564}
565
566void hdd_ipv6_callback_register(hdd_adapter_t *pAdapter, int fenable)
567{
568
569 int ret = 0;
570
571 if (fenable)
572 {
573
574 if(!pAdapter->ipv6_notifier_registered)
575 {
576
577 // Register IPv6 notifier to notify if any change in IP
578 // So that we can reconfigure the offload parameters
579 pAdapter->ipv6_notifier.notifier_call =
580 wlan_hdd_ipv6_changed;
581 ret = register_inet6addr_notifier(&pAdapter->ipv6_notifier);
582 if (ret)
583 {
584 hddLog(LOGE, FL("Failed to register IPv6 notifier"));
585 }
586 else
587 {
588 hddLog(LOG1, FL("Registered IPv6 notifier"));
589 pAdapter->ipv6_notifier_registered = true;
590 }
591 }
592 }
593 else
594 {
595
596 if (pAdapter->ipv6_notifier_registered)
597 {
598 hddLog(LOG1, FL("Unregistered IPv6 notifier"));
599 unregister_inet6addr_notifier(&pAdapter->ipv6_notifier);
600 pAdapter->ipv6_notifier_registered = false;
601 }
602
603 }
604
605}
606
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530607/*
608 * Function: hdd_conf_hostoffload
609 * Central function to configure the supported offloads,
610 * either enable or disable them.
611 */
612void hdd_conf_hostoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
613{
614 hdd_context_t *pHddCtx = NULL;
615 v_CONTEXT_t *pVosContext = NULL;
616 VOS_STATUS vstatus = VOS_STATUS_E_FAILURE;
617
618 hddLog(VOS_TRACE_LEVEL_INFO, FL("Configuring offloads with flag: %d"),
619 fenable);
620
621 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
622
623 if (NULL == pVosContext)
624 {
625 hddLog(VOS_TRACE_LEVEL_ERROR, FL(" Global VOS context is Null"));
626 return;
627 }
628
629 //Get the HDD context.
630 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
631
632 if (NULL == pHddCtx)
633 {
634 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: HDD context is Null", __func__);
635 return;
636 }
637
638 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
639 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
640 {
641 if (fenable)
642 {
643 if (eConnectionState_Associated ==
644 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)
645 {
646 if ((pHddCtx->cfg_ini->fhostArpOffload))
647 {
648 /*
649 * Configure the ARP Offload.
650 * Even if it fails we have to reconfigure the MC/BC
651 * filter flag as we want RIVA not to drop BroadCast
652 * Packets
653 */
654 hddLog(VOS_TRACE_LEVEL_INFO,
655 FL("Calling ARP Offload with flag: %d"), fenable);
656 vstatus = hdd_conf_arp_offload(pAdapter, fenable);
657 pHddCtx->configuredMcastBcastFilter &=
658 ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST);
659
660 if (!VOS_IS_STATUS_SUCCESS(vstatus))
661 {
662 hddLog(VOS_TRACE_LEVEL_ERROR,
663 "Failed to enable ARPOFfloadFeature %d",
664 vstatus);
665 }
666 }
667 //Configure GTK_OFFLOAD
668#ifdef WLAN_FEATURE_GTK_OFFLOAD
669 hdd_conf_gtk_offload(pAdapter, fenable);
670#endif
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530671
672#ifdef WLAN_NS_OFFLOAD
673 if (pHddCtx->cfg_ini->fhostNSOffload)
674 {
675 /*
676 * Configure the NS Offload.
677 * Even if it fails we have to reconfigure the MC/BC filter flag
678 * as we want RIVA not to drop Multicast Packets
679 */
680
681 hddLog(VOS_TRACE_LEVEL_INFO,
682 FL("Calling NS Offload with flag: %d"), fenable);
683 hdd_conf_ns_offload(pAdapter, fenable);
684 pHddCtx->configuredMcastBcastFilter &=
685 ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST);
686 }
687#endif
Atul Mittal37385d72014-03-27 18:15:03 +0530688
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530689 }
Atul Mittal37385d72014-03-27 18:15:03 +0530690 hdd_ipv6_callback_register(pAdapter, fenable);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530691 }
692 else
693 {
694 //Disable ARPOFFLOAD
695 if (pHddCtx->cfg_ini->fhostArpOffload)
696 {
697 vstatus = hdd_conf_arp_offload(pAdapter, fenable);
698 if (!VOS_IS_STATUS_SUCCESS(vstatus))
699 {
700 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530701 "Failed to disable ARPOffload Feature %d", vstatus);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530702 }
703 }
704 //Disable GTK_OFFLOAD
705#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530706 hdd_conf_gtk_offload(pAdapter, fenable);
707#endif
708
709#ifdef WLAN_NS_OFFLOAD
710 //Disable NSOFFLOAD
711 if (pHddCtx->cfg_ini->fhostNSOffload)
712 {
713 hdd_conf_ns_offload(pAdapter, fenable);
714 }
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530715#endif
Atul Mittal37385d72014-03-27 18:15:03 +0530716 hdd_ipv6_callback_register(pAdapter, fenable);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530717 }
718 }
719 return;
720}
721
Atul Mittal37385d72014-03-27 18:15:03 +0530722
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530723#ifdef WLAN_NS_OFFLOAD
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530724/**----------------------------------------------------------------------------
725
726 \brief hdd_conf_ns_offload() - Configure NS offload
727
728 Called during SUSPEND to configure the NS offload (MC BC filter) which
729 reduces power consumption.
730
731 \param - pAdapter - Adapter context for which NS offload is to be configured
732 \param - fenable - 0 - disable.
733 1 - enable. (with IPv6 notifier registration)
734 2 - enable. (without IPv6 notifier registration)
735
736 \return - void
737
738 ---------------------------------------------------------------------------*/
739void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, int fenable)
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530740{
741 struct inet6_dev *in6_dev;
742 struct inet6_ifaddr *ifp;
743 struct list_head *p;
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530744 int slot_index = NS_DEFAULT_SLOT_INDEX;
Girish Gowli1b6114f2014-05-17 17:17:09 +0530745 tANI_U8 **selfIPv6Addr = NULL;
746 tANI_U8 *selfIPv6AddrValid = NULL;
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530747 tSirHostOffloadReq offLoadRequest;
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530748 hdd_context_t *pHddCtx;
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530749 tHalHandle halHandle;
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530750
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530751 int i = 0, slot = 0;
752 int ret = 0;
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530753 eHalStatus returnStatus;
754
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530755 ENTER();
756 hddLog(LOG1, FL(" fenable = %d"), fenable);
757
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530758 if (NULL == pAdapter)
759 {
760 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD adapter is Null"));
761 return;
762 }
763
764 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530765 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
766
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530767 ret = wlan_hdd_validate_context(pHddCtx);
768
769 if (0 != ret)
770 {
771 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
772 FL("HDD context is not valid"));
773 return;
774 }
775
776 if (sme_IsFeatureSupportedByFW(EXTENDED_NSOFFLOAD_SLOT))
777 {
778 slot_index = NS_EXTENDED_SLOT_INDEX;
779 }
780
781 hddLog(VOS_TRACE_LEVEL_INFO, FL("slot_idex = %d"), slot_index);
782
783 selfIPv6AddrValid =
784 (tANI_U8 *)vos_mem_malloc(sizeof(tANI_U8) * slot_index);
785
786 if (NULL == selfIPv6AddrValid)
787 {
788 hddLog (VOS_TRACE_LEVEL_ERROR, FL("Failed to allocate memory for"
789 " selfIPv6AddrValid"));
790 goto end;
791 }
792
793 vos_mem_zero(selfIPv6AddrValid, slot_index * sizeof(tANI_U8));
794
795 selfIPv6Addr = (tANI_U8 **)vos_mem_malloc(sizeof(tANI_U8 *) * slot_index);
796
797 if (NULL == selfIPv6Addr)
798 {
799 hddLog (VOS_TRACE_LEVEL_ERROR, FL("Failed to allocate memory for"
800 " selfIPv6Addr"));
801 goto end;
802 }
803
804 vos_mem_zero(selfIPv6Addr, slot_index * sizeof(tANI_U8 *));
805
806 for (slot = 0; slot < slot_index; slot++)
807 {
808 selfIPv6Addr[slot] =
809 (tANI_U8 *)vos_mem_malloc(SIR_MAC_IPV6_ADDR_LEN);
810 if (NULL == selfIPv6Addr[slot])
811 {
812 hddLog (VOS_TRACE_LEVEL_ERROR, FL("Failed to allocate memory"
813 "for selfIPv6Addr"));
814 goto end;
815 }
816 vos_mem_zero(selfIPv6Addr[slot], SIR_MAC_IPV6_ADDR_LEN);
817 }
818
819 i = 0;
820
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530821 if (fenable)
822 {
823 in6_dev = __in6_dev_get(pAdapter->dev);
824 if (NULL != in6_dev)
825 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530826 list_for_each(p, &in6_dev->addr_list)
827 {
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530828 if (i >= slot_index)
829 {
830 hddLog (VOS_TRACE_LEVEL_ERROR,
831 FL("IPv6 address list is greater than IPv6"
832 "address supported by firmware"));
833 hddLog (VOS_TRACE_LEVEL_ERROR,
834 FL("FW supported IPv6 address = %d"), slot_index);
835 break;
836 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530837 ifp = list_entry(p, struct inet6_ifaddr, if_list);
838 switch(ipv6_addr_src_scope(&ifp->addr))
839 {
840 case IPV6_ADDR_SCOPE_LINKLOCAL:
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530841 vos_mem_copy(selfIPv6Addr[i], &ifp->addr.s6_addr,
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530842 sizeof(ifp->addr.s6_addr));
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530843 selfIPv6AddrValid[i] = SIR_IPV6_ADDR_VALID;
Hardik Kantilal Patel1341bdf2013-08-22 20:27:15 +0530844 hddLog (VOS_TRACE_LEVEL_INFO,
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530845 FL("Found IPV6_ADDR_SCOPE_LINKLOCAL Address : %pI6"),
846 selfIPv6Addr[i]);
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530847 break;
848 case IPV6_ADDR_SCOPE_GLOBAL:
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530849 vos_mem_copy(selfIPv6Addr[i], &ifp->addr.s6_addr,
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530850 sizeof(ifp->addr.s6_addr));
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530851 selfIPv6AddrValid[i] = SIR_IPV6_ADDR_VALID;
Hardik Kantilal Patel1341bdf2013-08-22 20:27:15 +0530852 hddLog (VOS_TRACE_LEVEL_INFO,
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530853 FL("Found IPV6_ADDR_SCOPE_GLOBAL Address : %pI6"),
854 selfIPv6Addr[i]);
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530855 break;
856 default:
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530857 hddLog(VOS_TRACE_LEVEL_ERROR,
858 FL("The Scope %d is not supported"),
859 ipv6_addr_src_scope(&ifp->addr));
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530860 }
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530861 if (selfIPv6AddrValid[i] == SIR_IPV6_ADDR_VALID)
862 {
863 i++;
864 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530865 }
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530866
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530867 vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest));
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530868 for (i =0; i < slot_index; i++)
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530869 {
870 if (selfIPv6AddrValid[i])
871 {
872 //Filling up the request structure
873 /* Filling the selfIPv6Addr with solicited address
874 * A Solicited-Node multicast address is created by
875 * taking the last 24 bits of a unicast or anycast
876 * address and appending them to the prefix
877 *
878 * FF02:0000:0000:0000:0000:0001:FFXX:XX
879 *
880 * here XX is the unicast/anycast bits
881 */
882 offLoadRequest.nsOffloadInfo.selfIPv6Addr[0] = 0xFF;
883 offLoadRequest.nsOffloadInfo.selfIPv6Addr[1] = 0x02;
884 offLoadRequest.nsOffloadInfo.selfIPv6Addr[11] = 0x01;
885 offLoadRequest.nsOffloadInfo.selfIPv6Addr[12] = 0xFF;
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530886 offLoadRequest.nsOffloadInfo.selfIPv6Addr[13] =
887 selfIPv6Addr[i][13];
888 offLoadRequest.nsOffloadInfo.selfIPv6Addr[14] =
889 selfIPv6Addr[i][14];
890 offLoadRequest.nsOffloadInfo.selfIPv6Addr[15] =
891 selfIPv6Addr[i][15];
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530892 offLoadRequest.nsOffloadInfo.slotIdx = i;
893
894 vos_mem_copy(&offLoadRequest.nsOffloadInfo.targetIPv6Addr[0],
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530895 selfIPv6Addr[i], sizeof(tANI_U8)*SIR_MAC_IPV6_ADDR_LEN);
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530896 vos_mem_copy(&offLoadRequest.nsOffloadInfo.selfMacAddr,
897 &pAdapter->macAddressCurrent.bytes,
898 sizeof(tANI_U8)*SIR_MAC_ADDR_LEN);
899
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530900 offLoadRequest.nsOffloadInfo.targetIPv6AddrValid[0] =
901 SIR_IPV6_ADDR_VALID;
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530902 offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD;
903 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
904
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530905 hddLog (VOS_TRACE_LEVEL_INFO,
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530906 FL("configuredMcastBcastFilter: %d"
907 "NSOffload Slot = %d"),
908 pHddCtx->configuredMcastBcastFilter, i);
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530909
Kiet Lamc8e1eb52013-10-24 00:30:49 +0530910 if ((VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid)
Amar Singhald08ce752014-03-21 16:28:27 -0700911 && ((HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST ==
912 pHddCtx->sus_res_mcastbcast_filter) ||
913 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
914 pHddCtx->sus_res_mcastbcast_filter)) &&
915 (!WDA_IS_MCAST_FLT_ENABLE_IN_FW ||
916 (WDA_IS_MCAST_FLT_ENABLE_IN_FW &&
917 !(pHddCtx->cfg_ini->fEnableMCAddrList))))
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530918 {
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530919 offLoadRequest.enableOrDisable =
Amar Singhald08ce752014-03-21 16:28:27 -0700920 SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE;
Sushant Kaushik439d4c72014-05-12 16:39:51 +0530921 hddLog (VOS_TRACE_LEVEL_INFO,
922 FL("Set offLoadRequest with %d"),
923 offLoadRequest.enableOrDisable);
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530924 }
925
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530926 vos_mem_copy(&offLoadRequest.params.hostIpv6Addr,
927 &offLoadRequest.nsOffloadInfo.targetIPv6Addr[0],
928 sizeof(tANI_U8)*SIR_MAC_IPV6_ADDR_LEN);
929
930 hddLog (VOS_TRACE_LEVEL_INFO,
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530931 FL("Setting NSOffload with solicitedIp: %pI6,"
932 "targetIp: %pI6"),
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530933 offLoadRequest.nsOffloadInfo.selfIPv6Addr,
934 offLoadRequest.nsOffloadInfo.targetIPv6Addr[0]);
935
936 //Configure the Firmware with this
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530937 returnStatus = sme_SetHostOffload(halHandle,
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530938 pAdapter->sessionId, &offLoadRequest);
939 if(eHAL_STATUS_SUCCESS != returnStatus)
940 {
941 hddLog(VOS_TRACE_LEVEL_ERROR,
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530942 FL("Failed to enable HostOffload feature with"
943 " status: %d"), returnStatus);
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530944 }
945 vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest));
946 }
947 }
948 }
949 else
950 {
951 hddLog(VOS_TRACE_LEVEL_ERROR,
952 FL("IPv6 dev does not exist. Failed to request NSOffload"));
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530953 goto end;
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530954 }
955 }
956 else
957 {
958 //Disable NSOffload
959 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
960 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
961 offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD;
962
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530963 for (i = 0; i < slot_index; i++)
Vinay Krishna Erannab29c6142014-01-07 12:20:51 +0530964 {
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530965 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Disable Slot= %d"), i);
Vinay Krishna Erannab29c6142014-01-07 12:20:51 +0530966 offLoadRequest.nsOffloadInfo.slotIdx = i;
967 if (eHAL_STATUS_SUCCESS !=
Vinay Krishna Eranna911a3b82014-01-07 12:20:51 +0530968 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
969 pAdapter->sessionId, &offLoadRequest))
Vinay Krishna Erannab29c6142014-01-07 12:20:51 +0530970 {
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530971 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failure to disable"
972 " %d Slot"), i);
Vinay Krishna Erannab29c6142014-01-07 12:20:51 +0530973 }
974 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530975 }
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530976end:
977 while (slot > 0 && selfIPv6Addr[--slot])
978 {
979 vos_mem_free(selfIPv6Addr[slot]);
980 }
981 if (selfIPv6Addr)
982 {
983 vos_mem_free(selfIPv6Addr);
984 }
985 if (selfIPv6AddrValid)
986 {
987 vos_mem_free(selfIPv6AddrValid);
988 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530989 return;
990}
991#endif
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530992
993void hdd_ipv4_notifier_work_queue(struct work_struct *work)
994{
995 hdd_adapter_t* pAdapter =
996 container_of(work, hdd_adapter_t, ipv4NotifierWorkQueue);
997 hdd_context_t *pHddCtx;
998 int status;
999
1000 hddLog(LOG1, FL("Reconfiguring ARP Offload"));
1001 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1002 status = wlan_hdd_validate_context(pHddCtx);
1003 if (0 != status)
1004 {
1005 hddLog(LOGE, FL("HDD context is invalid"));
1006 return;
1007 }
1008
Deepthi Gowri5933f402014-01-23 17:48:24 +05301009 if ( VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid)
1010 {
1011 pHddCtx->sus_res_mcastbcast_filter =
1012 pHddCtx->configuredMcastBcastFilter;
Sushant Kaushik439d4c72014-05-12 16:39:51 +05301013 hddLog(LOG1, FL("saving configuredMcastBcastFilter = %d"),
1014 pHddCtx->sus_res_mcastbcast_filter);
Deepthi Gowri5933f402014-01-23 17:48:24 +05301015 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
1016 }
1017
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301018 if ((eConnectionState_Associated ==
1019 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)
Deepthi Gowri5933f402014-01-23 17:48:24 +05301020 && (pHddCtx->hdd_wlan_suspended))
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301021 {
1022 // This invocation being part of the IPv4 registration callback,
1023 // we are passing second parameter as 2 to avoid registration
1024 // of IPv4 notifier again.
1025 hdd_conf_arp_offload(pAdapter, 2);
1026 }
1027}
1028
1029static int wlan_hdd_ipv4_changed(struct notifier_block *nb,
1030 unsigned long data, void *arg)
1031{
1032 struct in_ifaddr *ifa = (struct in_ifaddr *)arg;
1033 struct in_ifaddr **ifap = NULL;
1034 struct in_device *in_dev;
1035
1036 struct net_device *ndev = ifa->ifa_dev->dev;
1037 hdd_adapter_t *pAdapter =
1038 container_of(nb, struct hdd_adapter_s, ipv4_notifier);
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05301039 hdd_context_t *pHddCtx;
1040 int status;
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301041 if (pAdapter && pAdapter->dev == ndev)
1042 {
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05301043 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1044 status = wlan_hdd_validate_context(pHddCtx);
1045 if (0 != status)
1046 {
1047 hddLog(LOGE, FL("HDD context is invalid"));
1048 return NOTIFY_DONE;
1049 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301050 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
1051 {
1052 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
1053 ifap = &ifa->ifa_next)
1054 {
1055 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
1056 {
1057 break; /* found */
1058 }
1059 }
1060 }
1061 if(ifa && ifa->ifa_local)
1062 {
1063 schedule_work(&pAdapter->ipv4NotifierWorkQueue);
1064 }
1065 }
1066
1067 return NOTIFY_DONE;
1068}
1069
1070/**----------------------------------------------------------------------------
1071
1072 \brief hdd_conf_arp_offload() - Configure ARP offload
1073
1074 Called during SUSPEND to configure the ARP offload (MC BC filter) which
1075 reduces power consumption.
1076
1077 \param - pAdapter -Adapter context for which ARP offload is to be configured
1078 \param - fenable - 0 - disable.
1079 1 - enable. (with IPv4 notifier registration)
1080 2 - enable. (without IPv4 notifier registration)
1081
1082 \return -
1083 VOS_STATUS_SUCCESS - on successful operation
1084 VOS_STATUS_E_FAILURE - on failure of operation
1085-----------------------------------------------------------------------------*/
1086VOS_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, int fenable)
Jeff Johnson295189b2012-06-20 16:38:30 -07001087{
1088 struct in_ifaddr **ifap = NULL;
1089 struct in_ifaddr *ifa = NULL;
1090 struct in_device *in_dev;
1091 int i = 0;
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301092 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001093 tSirHostOffloadReq offLoadRequest;
Yathish9f22e662012-12-10 14:21:35 -08001094 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001095
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301096 hddLog(VOS_TRACE_LEVEL_ERROR, FL(" fenable = %d \n"), fenable);
Jeff Johnson295189b2012-06-20 16:38:30 -07001097
Jeff Johnson295189b2012-06-20 16:38:30 -07001098 if(fenable)
1099 {
1100 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
1101 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301102 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001103 ifap = &ifa->ifa_next)
1104 {
1105 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
1106 {
1107 break; /* found */
1108 }
1109 }
1110 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001111 if(ifa && ifa->ifa_local)
1112 {
1113 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
1114 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
1115
Arif Hussain6d2a3322013-11-17 19:50:10 -08001116 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001117
Amar Singhald53568e2013-09-26 11:03:45 -07001118 if (((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
1119 pHddCtx->sus_res_mcastbcast_filter) ||
1120 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
1121 pHddCtx->sus_res_mcastbcast_filter)) &&
1122 (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid))
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -07001123 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301124 offLoadRequest.enableOrDisable =
Amar Singhald53568e2013-09-26 11:03:45 -07001125 SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
1126 hddLog(VOS_TRACE_LEVEL_INFO,
1127 "offload: inside arp offload conditional check");
Jeff Johnson295189b2012-06-20 16:38:30 -07001128 }
Amar Singhald53568e2013-09-26 11:03:45 -07001129
1130 hddLog(VOS_TRACE_LEVEL_INFO, "offload: arp filter programmed = %d",
1131 offLoadRequest.enableOrDisable);
1132
Jeff Johnson295189b2012-06-20 16:38:30 -07001133 //converting u32 to IPV4 address
1134 for(i = 0 ; i < 4; i++)
1135 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301136 offLoadRequest.params.hostIpv4Addr[i] =
Jeff Johnson295189b2012-06-20 16:38:30 -07001137 (ifa->ifa_local >> (i*8) ) & 0xFF ;
1138 }
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301139 hddLog(VOS_TRACE_LEVEL_INFO, " Enable SME HostOffload: %d.%d.%d.%d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001140 offLoadRequest.params.hostIpv4Addr[0],
1141 offLoadRequest.params.hostIpv4Addr[1],
1142 offLoadRequest.params.hostIpv4Addr[2],
1143 offLoadRequest.params.hostIpv4Addr[3]);
1144
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301145 if (eHAL_STATUS_SUCCESS !=
1146 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1147 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -07001148 {
1149 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to enable HostOffload "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001150 "feature", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001151 return VOS_STATUS_E_FAILURE;
1152 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001153 }
1154 else
1155 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05301156 hddLog(VOS_TRACE_LEVEL_ERROR, FL("IP Address is not assigned"));
1157 return VOS_STATUS_E_AGAIN;
Jeff Johnson295189b2012-06-20 16:38:30 -07001158 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301159
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05301160 if (fenable == 1 && !pAdapter->ipv4_notifier_registered)
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301161 {
1162 // Register IPv4 notifier to notify if any change in IP
1163 // So that we can reconfigure the offload parameters
1164 pAdapter->ipv4_notifier.notifier_call =
1165 wlan_hdd_ipv4_changed;
1166 ret = register_inetaddr_notifier(&pAdapter->ipv4_notifier);
1167 if (ret)
1168 {
1169 hddLog(LOGE, FL("Failed to register IPv4 notifier"));
1170 }
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05301171 else
1172 {
1173 hddLog(LOG1, FL("Registered IPv4 notifier"));
1174 pAdapter->ipv4_notifier_registered = true;
1175 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301176 }
1177 return VOS_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07001178 }
1179 else
1180 {
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05301181 if (pAdapter->ipv4_notifier_registered)
1182 {
1183 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
1184 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
1185 pAdapter->ipv4_notifier_registered = false;
1186 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001187 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
1188 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
1189 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
1190
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301191 if (eHAL_STATUS_SUCCESS !=
1192 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1193 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -07001194 {
1195 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to disable host "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001196 "offload feature", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001197 return VOS_STATUS_E_FAILURE;
1198 }
1199 return VOS_STATUS_SUCCESS;
1200 }
1201}
1202
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301203/*
1204 * This function is called before setting mcbc filters
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301205 * to modify filter value considering Different Offloads
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301206*/
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301207void hdd_mcbc_filter_modification(hdd_context_t* pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301208 tANI_U8 *pMcBcFilter)
1209{
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301210 if (NULL == pHddCtx)
1211 {
1212 hddLog(VOS_TRACE_LEVEL_ERROR, FL("NULL HDD context passed"));
1213 return;
1214 }
1215
1216 *pMcBcFilter = pHddCtx->configuredMcastBcastFilter;
1217 if (pHddCtx->cfg_ini->fhostArpOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301218 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301219 /* ARP offload is enabled, do not block bcast packets at RXP
1220 * Will be using Bitmasking to reset the filter. As we have
1221 * disable Broadcast filtering, Anding with the negation
1222 * of Broadcast BIT
1223 */
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301224 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301225 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301226
1227#ifdef WLAN_NS_OFFLOAD
1228 if (pHddCtx->cfg_ini->fhostNSOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301229 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301230 /* NS offload is enabled, do not block mcast packets at RXP
1231 * Will be using Bitmasking to reset the filter. As we have
1232 * disable Multicast filtering, Anding with the negation
1233 * of Multicast BIT
1234 */
1235 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301236 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301237#endif
1238
Amar Singhald08ce752014-03-21 16:28:27 -07001239 if ((pHddCtx->cfg_ini->fEnableMCAddrList) && WDA_IS_MCAST_FLT_ENABLE_IN_FW)
1240 {
1241 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST);
1242 }
1243
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301244 pHddCtx->configuredMcastBcastFilter = *pMcBcFilter;
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301245}
1246
Jeff Johnson295189b2012-06-20 16:38:30 -07001247void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter)
1248{
1249 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001250 tpSirWlanSetRxpFilters wlanRxpFilterParam =
1251 vos_mem_malloc(sizeof(tSirWlanSetRxpFilters));
1252 if(NULL == wlanRxpFilterParam)
1253 {
1254 hddLog(VOS_TRACE_LEVEL_FATAL,
1255 "%s: vos_mem_alloc failed ", __func__);
1256 return;
1257 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001258 hddLog(VOS_TRACE_LEVEL_INFO,
1259 "%s: Configuring Mcast/Bcast Filter Setting. setfilter %d", __func__, setfilter);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301260 if (TRUE == setfilter)
1261 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301262 hdd_mcbc_filter_modification(pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301263 &wlanRxpFilterParam->configuredMcstBcstFilterSetting);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301264 }
1265 else
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301266 {
1267 /*Use the current configured value to clear*/
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301268 wlanRxpFilterParam->configuredMcstBcstFilterSetting =
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301269 pHddCtx->configuredMcastBcastFilter;
1270 }
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301271
Jeff Johnson295189b2012-06-20 16:38:30 -07001272 wlanRxpFilterParam->setMcstBcstFilter = setfilter;
Jeff Johnson295189b2012-06-20 16:38:30 -07001273 halStatus = sme_ConfigureRxpFilter(pHddCtx->hHal, wlanRxpFilterParam);
Chilam Ngc4244af2013-04-01 15:37:32 -07001274 if (eHAL_STATUS_SUCCESS != halStatus)
1275 vos_mem_free(wlanRxpFilterParam);
Jeff Johnson295189b2012-06-20 16:38:30 -07001276 if(setfilter && (eHAL_STATUS_SUCCESS == halStatus))
1277 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
1278}
1279
Jeff Johnson295189b2012-06-20 16:38:30 -07001280static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx,
1281 hdd_adapter_t *pAdapter)
1282{
1283 eHalStatus halStatus = eHAL_STATUS_FAILURE;
1284 tpSirWlanSuspendParam wlanSuspendParam =
1285 vos_mem_malloc(sizeof(tSirWlanSuspendParam));
1286
Amar Singhald53568e2013-09-26 11:03:45 -07001287 if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid) {
1288 pHddCtx->sus_res_mcastbcast_filter =
1289 pHddCtx->configuredMcastBcastFilter;
1290 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
1291 hddLog(VOS_TRACE_LEVEL_INFO, "offload: hdd_conf_suspend_ind");
1292 hddLog(VOS_TRACE_LEVEL_INFO, "configuredMCastBcastFilter saved = %d",
1293 pHddCtx->configuredMcastBcastFilter);
1294
1295 }
1296
Amar Singhal49fdfd52013-08-13 13:25:12 -07001297
Jeff Johnson295189b2012-06-20 16:38:30 -07001298 if(NULL == wlanSuspendParam)
1299 {
1300 hddLog(VOS_TRACE_LEVEL_FATAL,
1301 "%s: vos_mem_alloc failed ", __func__);
1302 return;
1303 }
1304
Amar Singhald53568e2013-09-26 11:03:45 -07001305 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001306 "%s: send wlan suspend indication", __func__);
1307
1308 if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER))
1309 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301310 //Configure supported OffLoads
1311 hdd_conf_hostoffload(pAdapter, TRUE);
1312 wlanSuspendParam->configuredMcstBcstFilterSetting = pHddCtx->configuredMcastBcastFilter;
Sushant Kaushik439d4c72014-05-12 16:39:51 +05301313 hddLog(VOS_TRACE_LEVEL_INFO,
1314 FL("saving configuredMcastBcastFilterSetting = %d"),
1315 wlanSuspendParam->configuredMcstBcstFilterSetting);
Jeff Johnson295189b2012-06-20 16:38:30 -07001316#ifdef WLAN_FEATURE_PACKET_FILTERING
madan mohan koyyalamudibfd9cef2013-07-01 18:39:37 +05301317 /* During suspend, configure MC Addr list filter to the firmware
1318 * function takes care of checking necessary conditions before
1319 * configuring.
1320 */
1321 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001322#endif
Amar Singhald08ce752014-03-21 16:28:27 -07001323
1324 if( (pHddCtx->cfg_ini->fEnableMCAddrList) && WDA_IS_MCAST_FLT_ENABLE_IN_FW)
1325 {
1326
1327 hddLog(VOS_TRACE_LEVEL_INFO, "offload: MCaddrlist: FW capability set ");
1328 pHddCtx->configuredMcastBcastFilter &=
1329 ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST);
1330 }
1331
1332 wlanSuspendParam->configuredMcstBcstFilterSetting =
1333 pHddCtx->configuredMcastBcastFilter;
Jeff Johnson295189b2012-06-20 16:38:30 -07001334 }
1335
1336 halStatus = sme_ConfigureSuspendInd(pHddCtx->hHal, wlanSuspendParam);
1337 if(eHAL_STATUS_SUCCESS == halStatus)
1338 {
1339 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
Chilam Ngc4244af2013-04-01 15:37:32 -07001340 } else {
c_hpothuffdb5272013-10-02 16:42:35 +05301341 hddLog(VOS_TRACE_LEVEL_ERROR,
1342 FL("sme_ConfigureSuspendInd returned failure %d"), halStatus);
Chilam Ngc4244af2013-04-01 15:37:32 -07001343 vos_mem_free(wlanSuspendParam);
Jeff Johnson295189b2012-06-20 16:38:30 -07001344 }
1345}
1346
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301347static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001348{
Chilam Ngc4244af2013-04-01 15:37:32 -07001349 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Yathish9f22e662012-12-10 14:21:35 -08001350 hdd_context_t* pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Chilam Ngc4244af2013-04-01 15:37:32 -07001351 tpSirWlanResumeParam wlanResumeParam;
Jeff Johnson295189b2012-06-20 16:38:30 -07001352
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301353 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001354 "%s: send wlan resume indication", __func__);
1355
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301356 wlanResumeParam = vos_mem_malloc(sizeof(tSirWlanResumeParam));
1357
1358 if (NULL == wlanResumeParam)
Jeff Johnson295189b2012-06-20 16:38:30 -07001359 {
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301360 hddLog(VOS_TRACE_LEVEL_FATAL,
1361 "%s: memory allocation failed for wlanResumeParam ", __func__);
1362 return;
Jeff Johnson295189b2012-06-20 16:38:30 -07001363 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001364
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301365 //Disable supported OffLoads
1366 hdd_conf_hostoffload(pAdapter, FALSE);
1367
1368 wlanResumeParam->configuredMcstBcstFilterSetting =
1369 pHddCtx->configuredMcastBcastFilter;
1370 halStatus = sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam);
1371 if (eHAL_STATUS_SUCCESS != halStatus)
1372 {
c_hpothuffdb5272013-10-02 16:42:35 +05301373 hddLog(VOS_TRACE_LEVEL_ERROR,
1374 "%s: sme_ConfigureResumeReq return failure %d", __func__, halStatus);
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301375 vos_mem_free(wlanResumeParam);
1376 }
1377
1378 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
1379
Amar Singhalf8ba2b82013-12-02 12:54:38 -08001380 if (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid) {
1381 pHddCtx->configuredMcastBcastFilter =
1382 pHddCtx->sus_res_mcastbcast_filter;
1383 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_FALSE;
1384 }
Amar Singhald53568e2013-09-26 11:03:45 -07001385
1386 hddLog(VOS_TRACE_LEVEL_INFO,
1387 "offload: in hdd_conf_resume_ind, restoring configuredMcastBcastFilter");
1388 hddLog(VOS_TRACE_LEVEL_INFO, "configuredMcastBcastFilter = %d",
1389 pHddCtx->configuredMcastBcastFilter);
Amar Singhal49fdfd52013-08-13 13:25:12 -07001390
Chilam Ngc4244af2013-04-01 15:37:32 -07001391
madan mohan koyyalamudibfd9cef2013-07-01 18:39:37 +05301392#ifdef WLAN_FEATURE_PACKET_FILTERING
1393 /* Filer was applied during suspend inditication
1394 * clear it when we resume.
1395 */
1396 wlan_hdd_set_mc_addr_list(pAdapter, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001397#endif
1398}
Jeff Johnson295189b2012-06-20 16:38:30 -07001399
Jeff Johnson295189b2012-06-20 16:38:30 -07001400//Suspend routine registered with Android OS
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001401void hdd_suspend_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001402{
1403 hdd_context_t *pHddCtx = NULL;
1404 v_CONTEXT_t pVosContext = NULL;
1405
Jeff Johnson295189b2012-06-20 16:38:30 -07001406 VOS_STATUS status;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301407 hdd_adapter_t *pAdapter = NULL;
1408 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301409 bool hdd_enter_bmps = FALSE;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001410
Jeff Johnson295189b2012-06-20 16:38:30 -07001411 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__);
1412
1413 //Get the global VOSS context.
1414 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1415 if(!pVosContext) {
1416 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1417 return;
1418 }
1419
1420 //Get the HDD context.
1421 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1422
1423 if(!pHddCtx) {
1424 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1425 return;
1426 }
1427
1428 if (pHddCtx->isLogpInProgress) {
1429 hddLog(VOS_TRACE_LEVEL_ERROR,
1430 "%s: Ignore suspend wlan, LOGP in progress!", __func__);
1431 return;
1432 }
1433
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301434 hdd_set_pwrparams(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001435 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1436 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1437 {
1438 pAdapter = pAdapterNode->pAdapter;
1439 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001440 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001441 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
1442
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001443 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001444 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1445 pAdapterNode = pNext;
1446 continue;
1447 }
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301448 /* Avoid multiple enter/exit BMPS in this while loop using
1449 * hdd_enter_bmps flag
1450 */
1451 if (FALSE == hdd_enter_bmps && (BMPS == pmcGetPmcState(pHddCtx->hHal)))
1452 {
1453 hdd_enter_bmps = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001454
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301455 /* If device was already in BMPS, and dynamic DTIM is set,
1456 * exit(set the device to full power) and enter BMPS again
1457 * to reflect new DTIM value */
1458 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
1459
1460 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
1461
1462 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1463 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001464#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1465 if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1466 {
1467 //stop the interface before putting the chip to standby
1468 netif_tx_disable(pAdapter->dev);
1469 netif_carrier_off(pAdapter->dev);
1470 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301471 else if (pHddCtx->cfg_ini->nEnableSuspend ==
Jeff Johnson295189b2012-06-20 16:38:30 -07001472 WLAN_MAP_SUSPEND_TO_DEEP_SLEEP)
1473 {
1474 //Execute deep sleep procedure
1475 hdd_enter_deep_sleep(pHddCtx, pAdapter);
1476 }
1477#endif
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301478
1479 /*Suspend notification sent down to driver*/
1480 hdd_conf_suspend_ind(pHddCtx, pAdapter);
1481
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301482 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1483 pAdapterNode = pNext;
1484 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301485 pHddCtx->hdd_wlan_suspended = TRUE;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301486
Jeff Johnson295189b2012-06-20 16:38:30 -07001487#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1488 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1489 {
1490 hdd_enter_standby(pHddCtx);
1491 }
1492#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001493
1494 return;
1495}
1496
1497static void hdd_PowerStateChangedCB
1498(
1499 v_PVOID_t callbackContext,
1500 tPmcState newState
1501)
1502{
1503 hdd_context_t *pHddCtx = callbackContext;
Mukul Sharmabb94ece2014-04-04 21:22:15 +05301504
Jeff Johnson295189b2012-06-20 16:38:30 -07001505 /* if the driver was not in BMPS during early suspend,
1506 * the dynamic DTIM is now updated at Riva */
1507 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended
1508 && pHddCtx->cfg_ini->enableDynamicDTIM
1509 && (pHddCtx->hdd_ignore_dtim_enabled == FALSE))
1510 {
1511 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1512 }
1513 spin_lock(&pHddCtx->filter_lock);
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301514 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended)
1515 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001516 spin_unlock(&pHddCtx->filter_lock);
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301517 if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid)
1518 {
Amar Singhald53568e2013-09-26 11:03:45 -07001519 pHddCtx->sus_res_mcastbcast_filter =
1520 pHddCtx->configuredMcastBcastFilter;
1521 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
1522
1523 hddLog(VOS_TRACE_LEVEL_INFO, "offload: callback to associated");
1524 hddLog(VOS_TRACE_LEVEL_INFO, "saving configuredMcastBcastFilter = %d",
1525 pHddCtx->configuredMcastBcastFilter);
1526 hddLog(VOS_TRACE_LEVEL_INFO,
1527 "offload: calling hdd_conf_mcastbcast_filter");
1528
1529 }
1530
Jeff Johnson295189b2012-06-20 16:38:30 -07001531 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001532 if(pHddCtx->hdd_mcastbcast_filter_set != TRUE)
1533 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__);
Mukul Sharmabb94ece2014-04-04 21:22:15 +05301534 }
Amar Singhal49fdfd52013-08-13 13:25:12 -07001535 else
Mihir Shete793209f2014-01-06 11:01:12 +05301536 {
1537 /* Android framework can send resume request when the WCN chip is
1538 * in IMPS mode. When the chip exits IMPS mode the firmware will
1539 * restore all the registers to the state they were before the chip
1540 * entered IMPS and so our hardware filter settings confgured by the
1541 * resume request will be lost. So reconfigure the filters on detecting
1542 * a change in the power state of the WCN chip.
1543 */
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301544 spin_unlock(&pHddCtx->filter_lock);
Mihir Shete793209f2014-01-06 11:01:12 +05301545 if (IMPS != newState)
1546 {
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301547 spin_lock(&pHddCtx->filter_lock);
Mihir Shete793209f2014-01-06 11:01:12 +05301548 if (FALSE == pHddCtx->hdd_wlan_suspended)
1549 {
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301550 spin_unlock(&pHddCtx->filter_lock);
Mihir Shete793209f2014-01-06 11:01:12 +05301551 hddLog(VOS_TRACE_LEVEL_INFO,
1552 "Not in IMPS/BMPS and suspended state");
1553 hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
1554 }
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301555 else
1556 {
1557 spin_unlock(&pHddCtx->filter_lock);
1558 }
Mihir Shete793209f2014-01-06 11:01:12 +05301559 }
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301560 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001561}
1562
Jeff Johnson295189b2012-06-20 16:38:30 -07001563void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx)
1564{
1565 v_CONTEXT_t pVosContext;
1566 tHalHandle smeContext;
1567
1568 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1569 if (NULL == pVosContext)
1570 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001571 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001572 return;
1573 }
1574 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1575 if (NULL == smeContext)
1576 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001577 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001578 return;
1579 }
1580
1581 spin_lock_init(&pHddCtx->filter_lock);
1582 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1583 pHddCtx->cfg_ini->nEnableSuspend)
1584 {
1585 pmcRegisterDeviceStateUpdateInd(smeContext,
1586 hdd_PowerStateChangedCB, pHddCtx);
1587 }
1588}
1589
1590void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx)
1591{
1592 v_CONTEXT_t pVosContext;
1593 tHalHandle smeContext;
1594
1595 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1596 if (NULL == pVosContext)
1597 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001598 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001599 return;
1600 }
1601 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1602 if (NULL == smeContext)
1603 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001604 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001605 return;
1606 }
1607
1608 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1609 pHddCtx->cfg_ini->nEnableSuspend)
1610 {
1611 pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB);
1612 }
1613}
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301614
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301615#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301616void hdd_conf_gtk_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301617{
1618 eHalStatus ret;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301619 tSirGtkOffloadParams hddGtkOffloadReqParams;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301620 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1621
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301622 if(fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301623 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301624 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1625 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags ))
1626 {
1627 vos_mem_copy(&hddGtkOffloadReqParams,
1628 &pHddStaCtx->gtkOffloadReqParams,
1629 sizeof (tSirGtkOffloadParams));
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301630
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301631 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1632 &hddGtkOffloadReqParams, pAdapter->sessionId);
1633 if (eHAL_STATUS_SUCCESS != ret)
1634 {
1635 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1636 "%s: sme_SetGTKOffload failed, returned %d",
1637 __func__, ret);
1638 return;
1639 }
1640
1641 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1642 "%s: sme_SetGTKOffload successfull", __func__);
1643 }
1644
1645 }
1646 else
1647 {
1648 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1649 (0 == memcmp(&pHddStaCtx->gtkOffloadReqParams.bssId,
1650 &pHddStaCtx->conn_info.bssId, WNI_CFG_BSSID_LEN)) &&
1651 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags))
1652 {
1653
1654 /* Host driver has previously offloaded GTK rekey */
1655 ret = sme_GetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301656 wlan_hdd_cfg80211_update_replayCounterCallback,
1657 pAdapter, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301658 if (eHAL_STATUS_SUCCESS != ret)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301659
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301660 {
1661 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1662 "%s: sme_GetGTKOffload failed, returned %d",
1663 __func__, ret);
1664 return;
1665 }
1666 else
1667 {
1668 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1669 "%s: sme_GetGTKOffload successful",
1670 __func__);
1671
1672 /* Sending GTK offload dissable */
1673 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
1674 sizeof (tSirGtkOffloadParams));
1675 hddGtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE;
1676 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301677 &hddGtkOffloadReqParams, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301678 if (eHAL_STATUS_SUCCESS != ret)
1679 {
1680 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1681 "%s: failed to dissable GTK offload, returned %d",
1682 __func__, ret);
1683 return;
1684 }
1685 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1686 "%s: successfully dissabled GTK offload request to HAL",
1687 __func__);
1688 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301689 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301690 }
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301691 return;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301692}
1693#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
Jeff Johnson295189b2012-06-20 16:38:30 -07001694
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001695void hdd_resume_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001696{
1697 hdd_context_t *pHddCtx = NULL;
1698 hdd_adapter_t *pAdapter = NULL;
1699 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1700 VOS_STATUS status;
1701 v_CONTEXT_t pVosContext = NULL;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001702
Jeff Johnson295189b2012-06-20 16:38:30 -07001703 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
1704
1705 //Get the global VOSS context.
1706 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1707 if(!pVosContext) {
1708 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1709 return;
1710 }
1711
1712 //Get the HDD context.
1713 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1714
1715 if(!pHddCtx) {
1716 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1717 return;
1718 }
1719
Agarwal Ashish971c2882013-10-30 20:11:12 +05301720 if (pHddCtx->isLogpInProgress)
1721 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001722 hddLog(VOS_TRACE_LEVEL_INFO,
1723 "%s: Ignore resume wlan, LOGP in progress!", __func__);
1724 return;
1725 }
1726
Jeff Johnson295189b2012-06-20 16:38:30 -07001727 pHddCtx->hdd_wlan_suspended = FALSE;
1728 /*loop through all adapters. Concurrency */
1729 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1730
1731 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1732 {
1733 pAdapter = pAdapterNode->pAdapter;
1734 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001735 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001736 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001737 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001738 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1739 pAdapterNode = pNext;
1740 continue;
1741 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301742
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301743
Jeff Johnson295189b2012-06-20 16:38:30 -07001744#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1745 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP)
1746 {
1747 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__);
1748 hdd_exit_deep_sleep(pAdapter);
1749 }
1750#endif
1751
1752 if(pHddCtx->hdd_ignore_dtim_enabled == TRUE)
1753 {
1754 /*Switch back to DTIM 1*/
1755 tSirSetPowerParamsReq powerRequest = { 0 };
1756
1757 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
1758 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07001759 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001760
1761 /*Disabled ModulatedDTIM if enabled on suspend*/
1762 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1763 powerRequest.uDTIMPeriod = 0;
1764
1765 /* Update ignoreDTIM and ListedInterval in CFG with default values */
1766 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1767 NULL, eANI_BOOLEAN_FALSE);
1768 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1769 NULL, eANI_BOOLEAN_FALSE);
1770
1771 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001772 "Switch to DTIM%d",powerRequest.uListenInterval);
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08001773 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001774
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301775 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
1776 {
1777 /* put the device into full power */
1778 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001779
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301780 /* put the device back into BMPS */
1781 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
Jeff Johnson295189b2012-06-20 16:38:30 -07001782
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301783 pHddCtx->hdd_ignore_dtim_enabled = FALSE;
1784 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001785 }
1786
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301787 hdd_conf_resume_ind(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001788 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1789 pAdapterNode = pNext;
1790 }
1791
1792#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1793 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY)
1794 {
1795 hdd_exit_standby(pHddCtx);
1796 }
1797#endif
1798
Jeff Johnson295189b2012-06-20 16:38:30 -07001799 return;
1800}
1801
Jeff Johnson295189b2012-06-20 16:38:30 -07001802VOS_STATUS hdd_wlan_reset_initialization(void)
1803{
Jeff Johnson295189b2012-06-20 16:38:30 -07001804 v_CONTEXT_t pVosContext = NULL;
1805
1806 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1807
1808 //Get the global VOSS context.
1809 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1810 if(!pVosContext)
1811 {
1812 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1813 return VOS_STATUS_E_FAILURE;
1814 }
1815
1816 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__);
1817
1818 // Prevent the phone from going to sleep
1819 hdd_prevent_suspend();
1820
Jeff Johnson295189b2012-06-20 16:38:30 -07001821 return VOS_STATUS_SUCCESS;
1822}
1823
1824
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001825/*
1826 * Based on the ioctl command recieved by HDD, put WLAN driver
1827 * into the quiet mode. This is the same as the early suspend
1828 * notification that driver used to listen
1829 */
1830void hdd_set_wlan_suspend_mode(bool suspend)
Jeff Johnson295189b2012-06-20 16:38:30 -07001831{
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001832 if (suspend)
1833 hdd_suspend_wlan();
1834 else
1835 hdd_resume_wlan();
Jeff Johnson295189b2012-06-20 16:38:30 -07001836}
1837
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001838static void hdd_ssr_timer_init(void)
1839{
1840 init_timer(&ssr_timer);
1841}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001842
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001843static void hdd_ssr_timer_del(void)
1844{
1845 del_timer(&ssr_timer);
1846 ssr_timer_started = false;
1847}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001848
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001849static void hdd_ssr_timer_cb(unsigned long data)
1850{
1851 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD SSR timer expired", __func__);
Sameer Thalappile5637f42013-08-07 15:46:55 -07001852
1853#ifdef WCN_PRONTO
1854 if (wcnss_hardware_type() == WCNSS_PRONTO_HW)
1855 wcnss_pronto_log_debug_regs();
1856#endif
1857
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001858 VOS_BUG(0);
1859}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001860
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001861static void hdd_ssr_timer_start(int msec)
1862{
1863 if(ssr_timer_started)
1864 {
1865 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: trying to start SSR timer when it's running"
1866 ,__func__);
1867 }
1868 ssr_timer.expires = jiffies + msecs_to_jiffies(msec);
1869 ssr_timer.function = hdd_ssr_timer_cb;
1870 add_timer(&ssr_timer);
1871 ssr_timer_started = true;
1872}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001873
Jeff Johnson295189b2012-06-20 16:38:30 -07001874/* the HDD interface to WLAN driver shutdown,
1875 * the primary shutdown function in SSR
1876 */
1877VOS_STATUS hdd_wlan_shutdown(void)
1878{
1879 VOS_STATUS vosStatus;
1880 v_CONTEXT_t pVosContext = NULL;
1881 hdd_context_t *pHddCtx = NULL;
1882 pVosSchedContext vosSchedContext = NULL;
c_hpothuffdb5272013-10-02 16:42:35 +05301883 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07001884
1885 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__);
1886
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001887 /* if re-init never happens, then do SSR1 */
1888 hdd_ssr_timer_init();
1889 hdd_ssr_timer_start(HDD_SSR_BRING_UP_TIME);
1890
Jeff Johnson295189b2012-06-20 16:38:30 -07001891 /* Get the global VOSS context. */
1892 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1893 if(!pVosContext) {
1894 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1895 return VOS_STATUS_E_FAILURE;
1896 }
1897 /* Get the HDD context. */
1898 pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1899 if(!pHddCtx) {
1900 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1901 return VOS_STATUS_E_FAILURE;
1902 }
c_hpothud662a352013-12-26 15:09:12 +05301903
1904 //Stop the traffic monitor timer
1905 if ( VOS_TIMER_STATE_RUNNING ==
1906 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
1907 {
1908 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
1909 }
1910
Jeff Johnson295189b2012-06-20 16:38:30 -07001911 hdd_reset_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001912 /* DeRegister with platform driver as client for Suspend/Resume */
1913 vosStatus = hddDeregisterPmOps(pHddCtx);
1914 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1915 {
1916 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
1917 }
1918
1919 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
1920 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1921 {
1922 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
1923 }
1924
1925 /* Disable IMPS/BMPS as we do not want the device to enter any power
1926 * save mode on its own during reset sequence
1927 */
1928 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1929 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1930 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1931
1932 vosSchedContext = get_vos_sched_ctxt();
1933
1934 /* Wakeup all driver threads */
1935 if(TRUE == pHddCtx->isMcThreadSuspended){
1936 complete(&vosSchedContext->ResumeMcEvent);
1937 pHddCtx->isMcThreadSuspended= FALSE;
1938 }
1939 if(TRUE == pHddCtx->isTxThreadSuspended){
1940 complete(&vosSchedContext->ResumeTxEvent);
1941 pHddCtx->isTxThreadSuspended= FALSE;
1942 }
1943 if(TRUE == pHddCtx->isRxThreadSuspended){
1944 complete(&vosSchedContext->ResumeRxEvent);
1945 pHddCtx->isRxThreadSuspended= FALSE;
1946 }
1947 /* Reset the Suspend Variable */
1948 pHddCtx->isWlanSuspended = FALSE;
1949
1950 /* Stop all the threads; we do not want any messages to be a processed,
1951 * any more and the best way to ensure that is to terminate the threads
1952 * gracefully.
1953 */
1954 /* Wait for MC to exit */
1955 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
1956 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
1957 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
1958 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
c_hpothuffdb5272013-10-02 16:42:35 +05301959 ret = wait_for_completion_interruptible(&vosSchedContext->McShutdown);
1960 if (0 >= ret)
1961 {
1962 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:wait on McShutdown failed %ld",
1963 __func__, ret);
1964 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001965
1966 /* Wait for TX to exit */
1967 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
1968 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
1969 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
1970 wake_up_interruptible(&vosSchedContext->txWaitQueue);
c_hpothuffdb5272013-10-02 16:42:35 +05301971 ret = wait_for_completion_interruptible(&vosSchedContext->TxShutdown);
1972 if (0 >= ret)
1973 {
1974 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:wait on TxShutdown failed %ld",
1975 __func__, ret);
1976 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001977
1978 /* Wait for RX to exit */
1979 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
1980 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
1981 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
1982 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
c_hpothuffdb5272013-10-02 16:42:35 +05301983
1984 ret = wait_for_completion_interruptible(&vosSchedContext->RxShutdown);
1985 if (0 >= ret)
1986 {
1987 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:wait on RxShutdown failed %ld",
1988 __func__, ret);
1989 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001990
1991#ifdef WLAN_BTAMP_FEATURE
1992 vosStatus = WLANBAP_Stop(pVosContext);
1993 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1994 {
1995 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1996 "%s: Failed to stop BAP",__func__);
1997 }
1998#endif //WLAN_BTAMP_FEATURE
1999 vosStatus = vos_wda_shutdown(pVosContext);
c_hpothuffdb5272013-10-02 16:42:35 +05302000 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2001 {
2002 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2003 "%s: Failed to stop wda %d", __func__, vosStatus);
2004 VOS_ASSERT(0);
2005 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002006
2007 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
2008 /* Stop SME - Cannot invoke vos_stop as vos_stop relies
2009 * on threads being running to process the SYS Stop
2010 */
Kiet Lama72a2322013-11-15 11:18:11 +05302011 vosStatus = sme_Stop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
c_hpothuffdb5272013-10-02 16:42:35 +05302012 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2013 {
2014 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2015 "%s: Failed to stop sme %d", __func__, vosStatus);
2016 VOS_ASSERT(0);
2017 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002018
2019 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
2020 /* Stop MAC (PE and HAL) */
2021 vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
c_hpothuffdb5272013-10-02 16:42:35 +05302022 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2023 {
2024 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2025 "%s: Failed to stop mac %d", __func__, vosStatus);
2026 VOS_ASSERT(0);
2027 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002028
2029 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
2030 /* Stop TL */
2031 vosStatus = WLANTL_Stop(pVosContext);
c_hpothuffdb5272013-10-02 16:42:35 +05302032 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2033 {
2034 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2035 "%s: Failed to stop TL %d", __func__, vosStatus);
2036 VOS_ASSERT(0);
2037 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002038
Jeff Johnson295189b2012-06-20 16:38:30 -07002039 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002040 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__);
2041 /* Clean up message queues of TX and MC thread */
2042 vos_sched_flush_mc_mqs(vosSchedContext);
2043 vos_sched_flush_tx_mqs(vosSchedContext);
2044 vos_sched_flush_rx_mqs(vosSchedContext);
2045
2046 /* Deinit all the TX and MC queues */
2047 vos_sched_deinit_mqs(vosSchedContext);
2048 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__);
2049
2050 /* shutdown VOSS */
2051 vos_shutdown(pVosContext);
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05302052
2053 /*mac context has already been released in mac_close call
2054 so setting it to NULL in hdd context*/
2055 pHddCtx->hHal = (tHalHandle)NULL;
2056
Jeff Johnson295189b2012-06-20 16:38:30 -07002057 if (free_riva_power_on_lock("wlan"))
2058 {
2059 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
2060 __func__);
2061 }
2062 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete"
2063 ,__func__);
2064 return VOS_STATUS_SUCCESS;
2065}
2066
2067
2068
2069/* the HDD interface to WLAN driver re-init.
2070 * This is called to initialize/start WLAN driver after a shutdown.
2071 */
2072VOS_STATUS hdd_wlan_re_init(void)
2073{
2074 VOS_STATUS vosStatus;
2075 v_CONTEXT_t pVosContext = NULL;
2076 hdd_context_t *pHddCtx = NULL;
2077 eHalStatus halStatus;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07002078#ifdef HAVE_WCNSS_CAL_DOWNLOAD
2079 int max_retries = 0;
2080#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002081#ifdef WLAN_BTAMP_FEATURE
2082 hdd_config_t *pConfig = NULL;
2083 WLANBAP_ConfigType btAmpConfig;
2084#endif
2085
Katya Nigam82a93062014-06-04 15:15:36 +05302086 struct device *dev = NULL;
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07002087 hdd_ssr_timer_del();
Jeff Johnson295189b2012-06-20 16:38:30 -07002088 hdd_prevent_suspend();
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08002089
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07002090#ifdef HAVE_WCNSS_CAL_DOWNLOAD
2091 /* wait until WCNSS driver downloads NV */
Yue Ma120f9ff2014-02-26 14:53:31 -08002092 while (!wcnss_device_ready() && 10 >= ++max_retries) {
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07002093 msleep(1000);
2094 }
Yue Ma120f9ff2014-02-26 14:53:31 -08002095 if (max_retries >= 10) {
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07002096 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
2097 goto err_re_init;
2098 }
2099#endif
2100
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07002101 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, TRUE);
2102
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08002103 /* The driver should always be initialized in STA mode after SSR */
2104 hdd_set_conparam(0);
2105
Katya Nigam82a93062014-06-04 15:15:36 +05302106 dev = wcnss_wlan_get_device();
2107 if (NULL == dev)
2108 {
2109 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wcnss dev is NULL",__func__);
2110 goto err_re_init;
2111 }
2112
Jeff Johnson295189b2012-06-20 16:38:30 -07002113 /* Re-open VOSS, it is a re-open b'se control transport was never closed. */
Katya Nigam82a93062014-06-04 15:15:36 +05302114 vosStatus = vos_open(&pVosContext, dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07002115 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2116 {
2117 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
2118 goto err_re_init;
2119 }
2120
2121 /* Get the HDD context. */
2122 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
2123 if(!pHddCtx)
2124 {
2125 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
2126 goto err_vosclose;
2127 }
2128
2129 /* Save the hal context in Adapter */
2130 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
2131 if ( NULL == pHddCtx->hHal )
2132 {
2133 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
2134 goto err_vosclose;
2135 }
2136
2137 /* Set the SME configuration parameters. */
2138 vosStatus = hdd_set_sme_config(pHddCtx);
2139 if ( VOS_STATUS_SUCCESS != vosStatus )
2140 {
2141 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
2142 goto err_vosclose;
2143 }
2144
2145 /* Initialize the WMM module */
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002146 vosStatus = hdd_wmm_init(pHddCtx, hddWmmDscpToUpMapInfra);
2147 vosStatus = hdd_wmm_init(pHddCtx, hddWmmDscpToUpMapP2p);
Jeff Johnson295189b2012-06-20 16:38:30 -07002148 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
2149 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002150 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002151 goto err_vosclose;
2152 }
2153
2154 vosStatus = vos_preStart( pHddCtx->pvosContext );
2155 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2156 {
2157 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
2158 goto err_vosclose;
2159 }
2160
2161 /* In the integrated architecture we update the configuration from
2162 the INI file and from NV before vOSS has been started so that
2163 the final contents are available to send down to the cCPU */
2164 /* Apply the cfg.ini to cfg.dat */
2165 if (FALSE == hdd_update_config_dat(pHddCtx))
2166 {
2167 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
2168 goto err_vosclose;
2169 }
2170
2171 /* Set the MAC Address, currently this is used by HAL to add self sta.
2172 * Remove this once self sta is added as part of session open. */
2173 halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID,
2174 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
2175 sizeof(pHddCtx->cfg_ini->intfMacAddr[0]));
2176 if (!HAL_STATUS_SUCCESS(halStatus))
2177 {
2178 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
2179 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus);
2180 goto err_vosclose;
2181 }
2182
2183 /* Start VOSS which starts up the SME/MAC/HAL modules and everything else
2184 Note: Firmware image will be read and downloaded inside vos_start API */
2185 vosStatus = vos_start( pVosContext );
2186 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2187 {
2188 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
2189 goto err_vosclose;
2190 }
2191
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07002192 /* Exchange capability info between Host and FW and also get versioning info from FW */
2193 hdd_exchange_version_and_caps(pHddCtx);
2194
Jeff Johnson295189b2012-06-20 16:38:30 -07002195 vosStatus = hdd_post_voss_start_config( pHddCtx );
2196 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2197 {
2198 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
2199 __func__);
2200 goto err_vosstop;
2201 }
2202
2203#ifdef WLAN_BTAMP_FEATURE
2204 vosStatus = WLANBAP_Open(pVosContext);
2205 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
2206 {
2207 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2208 "%s: Failed to open BAP",__func__);
2209 goto err_vosstop;
2210 }
2211 vosStatus = BSL_Init(pVosContext);
2212 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
2213 {
2214 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2215 "%s: Failed to Init BSL",__func__);
2216 goto err_bap_close;
2217 }
2218 vosStatus = WLANBAP_Start(pVosContext);
2219 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2220 {
2221 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2222 "%s: Failed to start TL",__func__);
2223 goto err_bap_close;
2224 }
2225 pConfig = pHddCtx->cfg_ini;
2226 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
2227 vosStatus = WLANBAP_SetConfig(&btAmpConfig);
2228#endif //WLAN_BTAMP_FEATURE
2229
2230 /* Restart all adapters */
2231 hdd_start_all_adapters(pHddCtx);
2232 pHddCtx->isLogpInProgress = FALSE;
Sameer Thalappilb511beb2013-09-09 17:11:51 -07002233 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07002234 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002235 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002236
2237 /* Register with platform driver as client for Suspend/Resume */
2238 vosStatus = hddRegisterPmOps(pHddCtx);
2239 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2240 {
2241 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
2242 goto err_bap_stop;
2243 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002244 /* Allow the phone to go to sleep */
2245 hdd_allow_suspend();
2246 /* register for riva power on lock */
2247 if (req_riva_power_on_lock("wlan"))
2248 {
2249 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
2250 __func__);
2251 goto err_unregister_pmops;
2252 }
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07002253 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07002254 goto success;
2255
2256err_unregister_pmops:
2257 hddDeregisterPmOps(pHddCtx);
2258
2259err_bap_stop:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002260#ifdef CONFIG_HAS_EARLYSUSPEND
2261 hdd_unregister_mcast_bcast_filter(pHddCtx);
2262#endif
2263 hdd_close_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002264#ifdef WLAN_BTAMP_FEATURE
Jeff Johnson32d95a32012-09-10 13:15:23 -07002265 WLANBAP_Stop(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07002266#endif
2267
2268#ifdef WLAN_BTAMP_FEATURE
2269err_bap_close:
2270 WLANBAP_Close(pVosContext);
2271#endif
2272
2273err_vosstop:
2274 vos_stop(pVosContext);
2275
2276err_vosclose:
2277 vos_close(pVosContext);
2278 vos_sched_close(pVosContext);
2279 if (pHddCtx)
2280 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002281 /* Unregister the Net Device Notifier */
2282 unregister_netdevice_notifier(&hdd_netdev_notifier);
2283 /* Clean up HDD Nlink Service */
2284 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07002285#ifdef WLAN_KD_READY_NOTIFIER
2286 nl_srv_exit(pHddCtx->ptt_pid);
2287#else
Jeff Johnson295189b2012-06-20 16:38:30 -07002288 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07002289#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07002290 /* Free up dynamically allocated members inside HDD Adapter */
2291 kfree(pHddCtx->cfg_ini);
2292 pHddCtx->cfg_ini= NULL;
2293
Jeff Johnson295189b2012-06-20 16:38:30 -07002294 wiphy_unregister(pHddCtx->wiphy);
2295 wiphy_free(pHddCtx->wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07002296 }
2297 vos_preClose(&pVosContext);
2298
2299#ifdef MEMORY_DEBUG
2300 vos_mem_exit();
2301#endif
2302
2303err_re_init:
2304 /* Allow the phone to go to sleep */
2305 hdd_allow_suspend();
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07002306 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07002307 VOS_BUG(0);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002308 return -EPERM;
Jeff Johnson295189b2012-06-20 16:38:30 -07002309
2310success:
2311 /* Trigger replay of BTC events */
2312 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
2313 return VOS_STATUS_SUCCESS;
2314}