blob: 1878331757e47b7e11a25d7cf95c2d6bb4b87bb3 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/**=============================================================================
43* wlan_hdd_early_suspend.c
44*
45* \brief power management functions
46*
47* Description
48* Copyright 2009 (c) Qualcomm, Incorporated.
49* All Rights Reserved.
50* Qualcomm Confidential and Proprietary.
51*
52==============================================================================**/
53/* $HEADER$ */
54
55/**-----------------------------------------------------------------------------
56* Include files
57* ----------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -070058
59#include <linux/pm.h>
60#include <linux/wait.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070061#include <wlan_hdd_includes.h>
62#include <wlan_qct_driver.h>
63#include <linux/wakelock.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070064
65#include "halTypes.h"
66#include "sme_Api.h"
67#include <vos_api.h>
68#include "vos_power.h"
69#include <vos_sched.h>
70#include <macInitApi.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070071#include <wlan_qct_sys.h>
72#include <wlan_btc_svc.h>
73#include <wlan_nlink_common.h>
74#include <wlan_hdd_main.h>
75#include <wlan_hdd_assoc.h>
76#include <wlan_hdd_dev_pwr.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070077#include <wlan_nlink_srv.h>
78#include <wlan_hdd_misc.h>
79
Jeff Johnson295189b2012-06-20 16:38:30 -070080#include <linux/semaphore.h>
81#include <wlan_hdd_hostapd.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070082#include "cfgApi.h"
83
84#ifdef WLAN_BTAMP_FEATURE
85#include "bapApi.h"
86#include "bap_hdd_main.h"
87#include "bap_hdd_misc.h"
88#endif
89
Jeff Johnsone7245742012-09-05 17:12:55 -070090#include <linux/wcnss_wlan.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070091#include <linux/inetdevice.h>
92#include <wlan_hdd_cfg.h>
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053093#include <wlan_hdd_cfg80211.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070094/**-----------------------------------------------------------------------------
95* Preprocessor definitions and constants
96* ----------------------------------------------------------------------------*/
97
98/**-----------------------------------------------------------------------------
99* Type declarations
100* ----------------------------------------------------------------------------*/
101
102/**-----------------------------------------------------------------------------
103* Function and variables declarations
104* ----------------------------------------------------------------------------*/
105#include "wlan_hdd_power.h"
106#include "wlan_hdd_packet_filtering.h"
107
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -0700108#define HDD_SSR_BRING_UP_TIME 10000
Jeff Johnson295189b2012-06-20 16:38:30 -0700109
110static eHalStatus g_full_pwr_status;
111static eHalStatus g_standby_status;
112
113extern VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx);
114extern VOS_STATUS vos_chipExitDeepSleepVREGHandler(
115 vos_call_status_type* status,
116 vos_power_cb_type callback,
117 v_PVOID_t user_data);
118extern void hdd_wlan_initial_scan(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700119
120extern struct notifier_block hdd_netdev_notifier;
Jeff Johnson295189b2012-06-20 16:38:30 -0700121extern tVOS_CON_MODE hdd_get_conparam ( void );
Jeff Johnson295189b2012-06-20 16:38:30 -0700122
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -0700123static struct timer_list ssr_timer;
124static bool ssr_timer_started;
Jeff Johnson295189b2012-06-20 16:38:30 -0700125
126//Callback invoked by PMC to report status of standby request
127void hdd_suspend_standby_cbk (void *callbackContext, eHalStatus status)
128{
129 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
130 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Standby status = %d", __func__, status);
131 g_standby_status = status;
132
133 if(eHAL_STATUS_SUCCESS == status)
134 {
135 pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY;
136 }
137 else
138 {
139 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__);
140 }
141
142 complete(&pHddCtx->standby_comp_var);
143}
144
145//Callback invoked by PMC to report status of full power request
146void hdd_suspend_full_pwr_callback(void *callbackContext, eHalStatus status)
147{
148 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
149 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Full Power status = %d", __func__, status);
150 g_full_pwr_status = status;
151
152 if(eHAL_STATUS_SUCCESS == status)
153 {
154 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
155 }
156 else
157 {
158 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
159 }
160
161 complete(&pHddCtx->full_pwr_comp_var);
162}
163
164eHalStatus hdd_exit_standby(hdd_context_t *pHddCtx)
165{
166 eHalStatus status = VOS_STATUS_SUCCESS;
167
168 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from standby",__func__);
169 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
170
171 g_full_pwr_status = eHAL_STATUS_FAILURE;
172 status = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback, pHddCtx,
173 eSME_FULL_PWR_NEEDED_BY_HDD);
174
175 if(status == eHAL_STATUS_PMC_PENDING)
176 {
177 //Block on a completion variable. Can't wait forever though
178 wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var,
179 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
180 status = g_full_pwr_status;
181 if(g_full_pwr_status != eHAL_STATUS_SUCCESS)
182 {
183 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
184 VOS_ASSERT(0);
185 goto failure;
186 }
187 }
188 else if(status != eHAL_STATUS_SUCCESS)
189 {
190 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d",
191 __func__, status);
192 VOS_ASSERT(0);
193 goto failure;
194 }
195 else
196 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
197
198failure:
199 //No blocking to reduce latency. No other device should be depending on WLAN
200 //to finish resume and WLAN won't be instantly on after resume
201 return status;
202}
203
204
205//Helper routine to put the chip into standby
206VOS_STATUS hdd_enter_standby(hdd_context_t *pHddCtx)
207{
208 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
209 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
210
211 //Disable IMPS/BMPS as we do not want the device to enter any power
212 //save mode on its own during suspend sequence
213 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
214 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
215
216 //Note we do not disable queues unnecessarily. Queues should already be disabled
217 //if STA is disconnected or the queue will be disabled as and when disconnect
218 //happens because of standby procedure.
219
220 //Ensure that device is in full power first. There is scope for optimization
221 //here especially in scenarios where PMC is already in IMPS or REQUEST_IMPS.
222 //Core s/w needs to be optimized to handle this. Until then we request full
223 //power before issuing request for standby.
224 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
225 g_full_pwr_status = eHAL_STATUS_FAILURE;
226 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback,
227 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
228
229 if(halStatus == eHAL_STATUS_PMC_PENDING)
230 {
231 //Block on a completion variable. Can't wait forever though
232 wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var,
233 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
234 if(g_full_pwr_status != eHAL_STATUS_SUCCESS)
235 {
236 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower Failed",__func__);
237 VOS_ASSERT(0);
238 vosStatus = VOS_STATUS_E_FAILURE;
239 goto failure;
240 }
241 }
242 else if(halStatus != eHAL_STATUS_SUCCESS)
243 {
244 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d",
245 __func__, halStatus);
246 VOS_ASSERT(0);
247 vosStatus = VOS_STATUS_E_FAILURE;
248 goto failure;
249 }
250
251 if(pHddCtx->hdd_mcastbcast_filter_set == TRUE) {
252 hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
253 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
254 }
255
256 //Request standby. Standby will cause the STA to disassociate first. TX queues
257 //will be disabled (by HDD) when STA disconnects. You do not want to disable TX
258 //queues here. Also do not assert if the failure code is eHAL_STATUS_PMC_NOT_NOW as PMC
259 //will send this failure code in case of concurrent sessions. Power Save cannot be supported
260 //when there are concurrent sessions.
261 INIT_COMPLETION(pHddCtx->standby_comp_var);
262 g_standby_status = eHAL_STATUS_FAILURE;
263 halStatus = sme_RequestStandby(pHddCtx->hHal, hdd_suspend_standby_cbk, pHddCtx);
264
265 if (halStatus == eHAL_STATUS_PMC_PENDING)
266 {
267 //Wait till WLAN device enters standby mode
268 wait_for_completion_timeout(&pHddCtx->standby_comp_var,
269 msecs_to_jiffies(WLAN_WAIT_TIME_STANDBY));
270 if (g_standby_status != eHAL_STATUS_SUCCESS && g_standby_status != eHAL_STATUS_PMC_NOT_NOW)
271 {
272 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__);
273 VOS_ASSERT(0);
274 vosStatus = VOS_STATUS_E_FAILURE;
275 goto failure;
276 }
277 }
278 else if (halStatus != eHAL_STATUS_SUCCESS && halStatus != eHAL_STATUS_PMC_NOT_NOW) {
279 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed - status %d",
280 __func__, halStatus);
281 VOS_ASSERT(0);
282 vosStatus = VOS_STATUS_E_FAILURE;
283 goto failure;
284 }
285 else
286 pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY;
287
288failure:
289 //Restore IMPS config
290 if(pHddCtx->cfg_ini->fIsImpsEnabled)
291 sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
292
293 //Restore BMPS config
294 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
295 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
296
297 return vosStatus;
298}
299
300
301//Helper routine for Deep sleep entry
302VOS_STATUS hdd_enter_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter)
303{
304 eHalStatus halStatus;
305 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
306 vos_call_status_type callType;
Jeff Johnsonbc676b42013-02-14 16:04:08 -0800307
Jeff Johnson295189b2012-06-20 16:38:30 -0700308 //Stop the Interface TX queue.
309 netif_tx_disable(pAdapter->dev);
310 netif_carrier_off(pAdapter->dev);
311
312 //Disable IMPS,BMPS as we do not want the device to enter any power
313 //save mode on it own during suspend sequence
314 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
315 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
316
317 //Ensure that device is in full power as we will touch H/W during vos_Stop
318 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
319 g_full_pwr_status = eHAL_STATUS_FAILURE;
320 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback,
321 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
322
323 if(halStatus == eHAL_STATUS_PMC_PENDING)
324 {
325 //Block on a completion variable. Can't wait forever though
326 wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var,
327 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
328 if(g_full_pwr_status != eHAL_STATUS_SUCCESS){
329 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
330 VOS_ASSERT(0);
331 }
332 }
333 else if(halStatus != eHAL_STATUS_SUCCESS)
334 {
335 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Request for Full Power failed",__func__);
336 VOS_ASSERT(0);
337 }
338
339 //Issue a disconnect. This is required to inform the supplicant that
340 //STA is getting disassociated and for GUI to be updated properly
341 INIT_COMPLETION(pAdapter->disconnect_comp_var);
342 halStatus = sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED);
343
344 //Success implies disconnect command got queued up successfully
345 if(halStatus == eHAL_STATUS_SUCCESS)
346 {
347 //Block on a completion variable. Can't wait forever though.
348 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
349 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
350 }
351
352
353 //None of the steps should fail after this. Continue even in case of failure
354 vosStatus = vos_stop( pHddCtx->pvosContext );
355 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
356
Jeff Johnson295189b2012-06-20 16:38:30 -0700357 vosStatus = vos_chipAssertDeepSleep( &callType, NULL, NULL );
358 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
359
360 //Vote off any PMIC voltage supplies
361 vosStatus = vos_chipPowerDown(NULL, NULL, NULL);
362
Jeff Johnson295189b2012-06-20 16:38:30 -0700363 pHddCtx->hdd_ps_state = eHDD_SUSPEND_DEEP_SLEEP;
364
365 //Restore IMPS config
366 if(pHddCtx->cfg_ini->fIsImpsEnabled)
367 sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
368
369 //Restore BMPS config
370 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
371 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
372
Jeff Johnson295189b2012-06-20 16:38:30 -0700373 return vosStatus;
374}
375
376VOS_STATUS hdd_exit_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter)
377{
378 VOS_STATUS vosStatus;
379 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -0700380
381 //Power Up Libra WLAN card first if not already powered up
382 vosStatus = vos_chipPowerUp(NULL,NULL,NULL);
383 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
384 {
385 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
386 "exiting", __func__);
387 goto err_deep_sleep;
388 }
389
Jeff Johnson295189b2012-06-20 16:38:30 -0700390 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
391 "%s: calling hdd_set_sme_config",__func__);
392 vosStatus = hdd_set_sme_config( pHddCtx );
393 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
394 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
395 {
396 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
397 "%s: Failed in hdd_set_sme_config",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700398 goto err_deep_sleep;
Jeff Johnson295189b2012-06-20 16:38:30 -0700399 }
400
401 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
402 "%s: calling vos_start",__func__);
403 vosStatus = vos_start( pHddCtx->pvosContext );
404 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
405 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
406 {
407 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
408 "%s: Failed in vos_start",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700409 goto err_deep_sleep;
Jeff Johnson295189b2012-06-20 16:38:30 -0700410 }
411
412 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
413 "%s: calling hdd_post_voss_start_config",__func__);
414 vosStatus = hdd_post_voss_start_config( pHddCtx );
415 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
416 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
417 {
418 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
419 "%s: Failed in hdd_post_voss_start_config",__func__);
420 goto err_voss_stop;
421 }
422
423
424 //Open a SME session for future operation
425 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pHddCtx,
426 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
427 if ( !HAL_STATUS_SUCCESS( halStatus ) )
428 {
429 hddLog(VOS_TRACE_LEVEL_FATAL,"sme_OpenSession() failed with status code %08d [x%08lx]",
430 halStatus, halStatus );
431 goto err_voss_stop;
432
433 }
434
435 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
436
437 //Trigger the initial scan
438 hdd_wlan_initial_scan(pHddCtx);
439
440 return VOS_STATUS_SUCCESS;
441
442err_voss_stop:
443 vos_stop(pHddCtx->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -0700444err_deep_sleep:
445 return VOS_STATUS_E_FAILURE;
446
447}
448
Yathish9f22e662012-12-10 14:21:35 -0800449VOS_STATUS hdd_conf_hostarpoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
Jeff Johnson295189b2012-06-20 16:38:30 -0700450{
451 struct in_ifaddr **ifap = NULL;
452 struct in_ifaddr *ifa = NULL;
453 struct in_device *in_dev;
454 int i = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700455 tSirHostOffloadReq offLoadRequest;
Yathish9f22e662012-12-10 14:21:35 -0800456 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700457
458 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700459
Jeff Johnson295189b2012-06-20 16:38:30 -0700460 if(fenable)
461 {
462 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
463 {
464 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
465 ifap = &ifa->ifa_next)
466 {
467 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
468 {
469 break; /* found */
470 }
471 }
472 }
473
474 if(ifa && ifa->ifa_local)
475 {
476 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
477 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
478
479 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Enabled \n", __func__);
480
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700481 if(pHddCtx->dynamic_mcbc_filter.enableCfg)
Jeff Johnson295189b2012-06-20 16:38:30 -0700482 {
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700483 if((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
484 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting) ||
485 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
486 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting))
487 {
488 offLoadRequest.enableOrDisable =
489 SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
490 }
491 }
492 else if((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
493 pHddCtx->cfg_ini->mcastBcastFilterSetting ) ||
494 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
495 pHddCtx->cfg_ini->mcastBcastFilterSetting))
496 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700497 offLoadRequest.enableOrDisable =
498 SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
499 }
500
501 //converting u32 to IPV4 address
502 for(i = 0 ; i < 4; i++)
503 {
504 offLoadRequest.params.hostIpv4Addr[i] =
505 (ifa->ifa_local >> (i*8) ) & 0xFF ;
506 }
507 hddLog(VOS_TRACE_LEVEL_WARN, " Enable SME HostOffload: %d.%d.%d.%d",
508 offLoadRequest.params.hostIpv4Addr[0],
509 offLoadRequest.params.hostIpv4Addr[1],
510 offLoadRequest.params.hostIpv4Addr[2],
511 offLoadRequest.params.hostIpv4Addr[3]);
512
513 if (eHAL_STATUS_SUCCESS !=
Jeff Johnsone7245742012-09-05 17:12:55 -0700514 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
515 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700516 {
517 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to enable HostOffload "
518 "feature\n", __func__);
519 return VOS_STATUS_E_FAILURE;
520 }
521 return VOS_STATUS_SUCCESS;
522 }
523 else
524 {
525 hddLog(VOS_TRACE_LEVEL_INFO, "%s:IP Address is not assigned \n", __func__);
526 return VOS_STATUS_E_AGAIN;
527 }
528 }
529 else
530 {
531 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
532 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
533 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
534
Jeff Johnsone7245742012-09-05 17:12:55 -0700535 if (eHAL_STATUS_SUCCESS != sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
536 &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700537 {
538 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to disable host "
539 "offload feature\n", __func__);
540 return VOS_STATUS_E_FAILURE;
541 }
542 return VOS_STATUS_SUCCESS;
543 }
544}
545
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530546/*
547 * This function is called before setting mcbc filters
548 * to modify filter value considering ARP
549*/
550void hdd_mcbc_filter_modification(hdd_context_t* pHddCtx, v_BOOL_t arpFlag,
551 tANI_U8 *pMcBcFilter)
552{
553 if (TRUE == arpFlag)
554 {
555 /*ARP offload is enabled, do not block bcast packets at RXP*/
556 if (pHddCtx->dynamic_mcbc_filter.enableCfg)
557 {
558 if ((HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
559 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting))
560 {
561 *pMcBcFilter = HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST;
562 }
563 else if ((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
564 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting))
565 {
566 *pMcBcFilter = HDD_MCASTBCASTFILTER_FILTER_NONE;
567 }
568 else
569 {
570 *pMcBcFilter = pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting;
571 }
572
573 pHddCtx->dynamic_mcbc_filter.enableSuspend = TRUE;
574 pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend = *pMcBcFilter;
575 }
576 else
577 {
578 if (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
579 pHddCtx->cfg_ini->mcastBcastFilterSetting)
580 {
581 *pMcBcFilter = HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST;
582 }
583 else if (HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
584 pHddCtx->cfg_ini->mcastBcastFilterSetting)
585 {
586 *pMcBcFilter = HDD_MCASTBCASTFILTER_FILTER_NONE;
587 }
588 else
589 {
590 *pMcBcFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
591 }
592
593 pHddCtx->dynamic_mcbc_filter.enableSuspend = FALSE;
594 }
595 }
596 else
597 {
598 if (pHddCtx->dynamic_mcbc_filter.enableCfg)
599 {
600 *pMcBcFilter = pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting;
601 pHddCtx->dynamic_mcbc_filter.enableSuspend = TRUE;
602 }
603 else
604 {
605 pHddCtx->dynamic_mcbc_filter.enableSuspend = FALSE;
606 *pMcBcFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
607 }
608 }
609}
610
Jeff Johnson295189b2012-06-20 16:38:30 -0700611void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter)
612{
613 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700614 tpSirWlanSetRxpFilters wlanRxpFilterParam =
615 vos_mem_malloc(sizeof(tSirWlanSetRxpFilters));
616 if(NULL == wlanRxpFilterParam)
617 {
618 hddLog(VOS_TRACE_LEVEL_FATAL,
619 "%s: vos_mem_alloc failed ", __func__);
620 return;
621 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700622 hddLog(VOS_TRACE_LEVEL_INFO,
623 "%s: Configuring Mcast/Bcast Filter Setting. setfilter %d", __func__, setfilter);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530624 if (TRUE == setfilter)
625 {
626 if (pHddCtx->cfg_ini->fhostArpOffload)
627 {
628 hdd_mcbc_filter_modification(pHddCtx, TRUE,
629 &wlanRxpFilterParam->configuredMcstBcstFilterSetting);
630 }
631 else
632 {
633 hdd_mcbc_filter_modification(pHddCtx, FALSE,
634 &wlanRxpFilterParam->configuredMcstBcstFilterSetting);
635 }
636 }
637 else
638 wlanRxpFilterParam->configuredMcstBcstFilterSetting =
639 pHddCtx->cfg_ini->mcastBcastFilterSetting;
640
Jeff Johnson295189b2012-06-20 16:38:30 -0700641 wlanRxpFilterParam->setMcstBcstFilter = setfilter;
Jeff Johnson295189b2012-06-20 16:38:30 -0700642 halStatus = sme_ConfigureRxpFilter(pHddCtx->hHal, wlanRxpFilterParam);
Chilam Ngc4244af2013-04-01 15:37:32 -0700643 if (eHAL_STATUS_SUCCESS != halStatus)
644 vos_mem_free(wlanRxpFilterParam);
Jeff Johnson295189b2012-06-20 16:38:30 -0700645 if(setfilter && (eHAL_STATUS_SUCCESS == halStatus))
646 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
647}
648
Jeff Johnson295189b2012-06-20 16:38:30 -0700649static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx,
650 hdd_adapter_t *pAdapter)
651{
652 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Madan Mohan Koyyalamudi51d87f72012-09-24 12:05:23 -0700653 VOS_STATUS vstatus = VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700654 tpSirWlanSuspendParam wlanSuspendParam =
655 vos_mem_malloc(sizeof(tSirWlanSuspendParam));
656
657 if(NULL == wlanSuspendParam)
658 {
659 hddLog(VOS_TRACE_LEVEL_FATAL,
660 "%s: vos_mem_alloc failed ", __func__);
661 return;
662 }
663
664 hddLog(VOS_TRACE_LEVEL_INFO,
665 "%s: send wlan suspend indication", __func__);
666
667 if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER))
668 {
669 if((pHddCtx->cfg_ini->fhostArpOffload) &&
670 (eConnectionState_Associated ==
671 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
672 {
Yathish9f22e662012-12-10 14:21:35 -0800673 vstatus = hdd_conf_hostarpoffload(pAdapter, TRUE);
Jeff Johnson43971f52012-07-17 12:26:56 -0700674 if (!VOS_IS_STATUS_SUCCESS(vstatus))
Jeff Johnson295189b2012-06-20 16:38:30 -0700675 {
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530676 hdd_mcbc_filter_modification(pHddCtx, FALSE,
677 &wlanSuspendParam->configuredMcstBcstFilterSetting);
Jeff Johnson295189b2012-06-20 16:38:30 -0700678 hddLog(VOS_TRACE_LEVEL_INFO,
679 "%s:Failed to enable ARPOFFLOAD Feature %d\n",
Jeff Johnson43971f52012-07-17 12:26:56 -0700680 __func__, vstatus);
Jeff Johnson295189b2012-06-20 16:38:30 -0700681 }
Jeff Johnson43971f52012-07-17 12:26:56 -0700682 else
683 {
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530684 hdd_mcbc_filter_modification(pHddCtx, TRUE,
685 &wlanSuspendParam->configuredMcstBcstFilterSetting);
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700686 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700687 }
688 else
689 {
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530690 hdd_mcbc_filter_modification(pHddCtx, FALSE,
691 &wlanSuspendParam->configuredMcstBcstFilterSetting);
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700692 if(pHddCtx->dynamic_mcbc_filter.enableCfg)
693 {
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700694 pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend =
Jeff Johnson43971f52012-07-17 12:26:56 -0700695 wlanSuspendParam->configuredMcstBcstFilterSetting;
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700696 }
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700697 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700698
699#ifdef WLAN_FEATURE_PACKET_FILTERING
700 if (pHddCtx->cfg_ini->isMcAddrListFilter)
701 {
702 /*Multicast addr list filter is enabled during suspend*/
703 if (((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
704 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT))
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530705 && pAdapter->mc_addr_list.mc_cnt
Jeff Johnson295189b2012-06-20 16:38:30 -0700706 && (eConnectionState_Associated ==
707 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
708 {
709 /*set the filter*/
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530710 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700711 }
712 }
713#endif
714 }
715
716 halStatus = sme_ConfigureSuspendInd(pHddCtx->hHal, wlanSuspendParam);
717 if(eHAL_STATUS_SUCCESS == halStatus)
718 {
719 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
Chilam Ngc4244af2013-04-01 15:37:32 -0700720 } else {
721 vos_mem_free(wlanSuspendParam);
Jeff Johnson295189b2012-06-20 16:38:30 -0700722 }
723}
724
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530725static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700726{
Chilam Ngc4244af2013-04-01 15:37:32 -0700727 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Jeff Johnson43971f52012-07-17 12:26:56 -0700728 VOS_STATUS vstatus;
Yathish9f22e662012-12-10 14:21:35 -0800729 hdd_context_t* pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Chilam Ngc4244af2013-04-01 15:37:32 -0700730 tpSirWlanResumeParam wlanResumeParam;
Jeff Johnson295189b2012-06-20 16:38:30 -0700731
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530732 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700733 "%s: send wlan resume indication", __func__);
734
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530735 if (pHddCtx->hdd_mcastbcast_filter_set == TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -0700736 {
Chilam Ngc4244af2013-04-01 15:37:32 -0700737 wlanResumeParam = vos_mem_malloc(sizeof(tSirWlanResumeParam));
738
739 if(NULL == wlanResumeParam)
740 {
741 hddLog(VOS_TRACE_LEVEL_FATAL,
742 "%s: vos_mem_alloc failed ", __func__);
743 return;
744 }
745
Gopichand Nakkalac6c91902013-05-29 18:53:35 +0530746 // adding the check for association here
747 if ((pHddCtx->cfg_ini->fhostArpOffload) &&
748 (eConnectionState_Associated ==
749 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
Jeff Johnson295189b2012-06-20 16:38:30 -0700750 {
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530751 vstatus = hdd_conf_hostarpoffload(pAdapter, FALSE);
752 if (!VOS_IS_STATUS_SUCCESS(vstatus))
753 {
Gopichand Nakkalac6c91902013-05-29 18:53:35 +0530754 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:Failed to disable ARPOFFLOAD "
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530755 "Feature %d\n", __func__, vstatus);
756 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700757 }
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530758 if (pHddCtx->dynamic_mcbc_filter.enableSuspend)
759 {
760 wlanResumeParam->configuredMcstBcstFilterSetting =
761 pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend;
762 }
763 else
764 {
765 wlanResumeParam->configuredMcstBcstFilterSetting =
766 pHddCtx->cfg_ini->mcastBcastFilterSetting;
767 }
Chilam Ngc4244af2013-04-01 15:37:32 -0700768 halStatus = sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam);
769 if (eHAL_STATUS_SUCCESS != halStatus)
770 vos_mem_free(wlanResumeParam);
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530771 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700772 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700773
Chilam Ngc4244af2013-04-01 15:37:32 -0700774
Jeff Johnson295189b2012-06-20 16:38:30 -0700775#ifdef WLAN_FEATURE_PACKET_FILTERING
776 if (pHddCtx->cfg_ini->isMcAddrListFilter)
777 {
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530778 /*Multicast addr filtering is enabled*/
779 if (pAdapter->mc_addr_list.isFilterApplied)
Jeff Johnson295189b2012-06-20 16:38:30 -0700780 {
781 /*Filter applied during suspend mode*/
782 /*Clear it here*/
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530783 wlan_hdd_set_mc_addr_list(pAdapter, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700784 }
785 }
786#endif
787}
Jeff Johnson295189b2012-06-20 16:38:30 -0700788
Jeff Johnson295189b2012-06-20 16:38:30 -0700789//Suspend routine registered with Android OS
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800790void hdd_suspend_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -0700791{
792 hdd_context_t *pHddCtx = NULL;
793 v_CONTEXT_t pVosContext = NULL;
794
795 hdd_adapter_t *pAdapter = NULL;
796 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
797 VOS_STATUS status;
Jeff Johnsonbc676b42013-02-14 16:04:08 -0800798
Jeff Johnson295189b2012-06-20 16:38:30 -0700799 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__);
800
801 //Get the global VOSS context.
802 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
803 if(!pVosContext) {
804 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
805 return;
806 }
807
808 //Get the HDD context.
809 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
810
811 if(!pHddCtx) {
812 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
813 return;
814 }
815
816 if (pHddCtx->isLogpInProgress) {
817 hddLog(VOS_TRACE_LEVEL_ERROR,
818 "%s: Ignore suspend wlan, LOGP in progress!", __func__);
819 return;
820 }
821
Jeff Johnson295189b2012-06-20 16:38:30 -0700822 /*loop through all adapters. TBD fix for Concurrency */
823 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
824 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
825 {
826 pAdapter = pAdapterNode->pAdapter;
827 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -0700828 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -0700829 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
830
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -0700831 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -0700832 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
833 pAdapterNode = pNext;
834 continue;
835 }
836
837#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
838 if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
839 {
840 //stop the interface before putting the chip to standby
841 netif_tx_disable(pAdapter->dev);
842 netif_carrier_off(pAdapter->dev);
843 }
844 else if (pHddCtx->cfg_ini->nEnableSuspend ==
845 WLAN_MAP_SUSPEND_TO_DEEP_SLEEP)
846 {
847 //Execute deep sleep procedure
848 hdd_enter_deep_sleep(pHddCtx, pAdapter);
849 }
850#endif
851
Jeff Johnsone7245742012-09-05 17:12:55 -0700852 //Apply Dynamic Dtim For P2P
853 //Only if ignoreDynamicDtimInP2pMode is not set in ini
Jeff Johnson295189b2012-06-20 16:38:30 -0700854 if((pHddCtx->cfg_ini->enableDynamicDTIM ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700855 pHddCtx->cfg_ini->enableModulatedDTIM) &&
856 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
857 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
858 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
Jeff Johnson295189b2012-06-20 16:38:30 -0700859 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
860 (eConnectionState_Associated ==
861 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
862 (pHddCtx->cfg_ini->fIsBmpsEnabled))
863 {
864 tSirSetPowerParamsReq powerRequest = { 0 };
865
866 powerRequest.uIgnoreDTIM = 1;
Yue Mac24062f2013-05-13 17:01:29 -0700867 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
868
Jeff Johnson295189b2012-06-20 16:38:30 -0700869 /*Back up the actual values from CFG */
870 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM,
871 &pHddCtx->hdd_actual_ignore_DTIM_value);
872 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL,
873 &pHddCtx->hdd_actual_LI_value);
874
875 if(pHddCtx->cfg_ini->enableModulatedDTIM)
876 {
877 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
878 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
879 }
880 else
881 {
882 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
883 }
884
885 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
886 *specified during Enter/Exit BMPS when LCD off*/
887 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
888 NULL, eANI_BOOLEAN_FALSE);
889 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
890 NULL, eANI_BOOLEAN_FALSE);
891
892 /* switch to the DTIM specified in cfg.ini */
893 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
894 "Switch to DTIM%d \n", powerRequest.uListenInterval);
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -0800895 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700896
897 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
898 {
899 /* put the device into full power */
900 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
901
902 /* put the device back into BMPS */
903 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
904
905 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
906 }
907 }
908
Jeff Johnson295189b2012-06-20 16:38:30 -0700909 /*Suspend notification sent down to driver*/
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530910 hdd_conf_suspend_ind(pHddCtx, pAdapter);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +0530911
912#ifdef WLAN_FEATURE_GTK_OFFLOAD
913 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
914 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
915 {
916 eHalStatus ret;
917 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
918 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
919 (TRUE == pHddStaCtx->gtkOffloadRequestParams.requested))
920 {
921 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
922 &pHddStaCtx->gtkOffloadRequestParams.gtkOffloadReqParams,
923 pAdapter->sessionId);
924 if (eHAL_STATUS_SUCCESS != ret)
925 {
926 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
927 "%s: sme_SetGTKOffload failed, returned %d",
928 __func__, ret);
929 }
930 pHddStaCtx->gtkOffloadRequestParams.requested = FALSE;
931 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
932 "%s: sme_SetGTKOffload successfull",
933 __func__);
934 }
935 }
936#endif
937
Jeff Johnson295189b2012-06-20 16:38:30 -0700938 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
939 pAdapterNode = pNext;
940 }
941 pHddCtx->hdd_wlan_suspended = TRUE;
942
943#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
944 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
945 {
946 hdd_enter_standby(pHddCtx);
947 }
948#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700949
950 return;
951}
952
953static void hdd_PowerStateChangedCB
954(
955 v_PVOID_t callbackContext,
956 tPmcState newState
957)
958{
959 hdd_context_t *pHddCtx = callbackContext;
960
961 /* if the driver was not in BMPS during early suspend,
962 * the dynamic DTIM is now updated at Riva */
963 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended
964 && pHddCtx->cfg_ini->enableDynamicDTIM
965 && (pHddCtx->hdd_ignore_dtim_enabled == FALSE))
966 {
967 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
968 }
969 spin_lock(&pHddCtx->filter_lock);
Gopichand Nakkalac1b11522013-03-25 15:25:33 +0530970 if((newState == BMPS) && pHddCtx->hdd_wlan_suspended) {
Jeff Johnson295189b2012-06-20 16:38:30 -0700971 spin_unlock(&pHddCtx->filter_lock);
972 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700973 if(pHddCtx->hdd_mcastbcast_filter_set != TRUE)
974 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__);
975 }
976 else
977 spin_unlock(&pHddCtx->filter_lock);
978}
979
980
981
982void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx)
983{
984 v_CONTEXT_t pVosContext;
985 tHalHandle smeContext;
986
987 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
988 if (NULL == pVosContext)
989 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700990 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700991 return;
992 }
993 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
994 if (NULL == smeContext)
995 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700996 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700997 return;
998 }
999
1000 spin_lock_init(&pHddCtx->filter_lock);
1001 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1002 pHddCtx->cfg_ini->nEnableSuspend)
1003 {
1004 pmcRegisterDeviceStateUpdateInd(smeContext,
1005 hdd_PowerStateChangedCB, pHddCtx);
1006 }
1007}
1008
1009void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx)
1010{
1011 v_CONTEXT_t pVosContext;
1012 tHalHandle smeContext;
1013
1014 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1015 if (NULL == pVosContext)
1016 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001017 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001018 return;
1019 }
1020 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1021 if (NULL == smeContext)
1022 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001023 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001024 return;
1025 }
1026
1027 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1028 pHddCtx->cfg_ini->nEnableSuspend)
1029 {
1030 pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB);
1031 }
1032}
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301033#ifdef WLAN_FEATURE_GTK_OFFLOAD
1034void wlan_hdd_update_and_dissable_gtk_offload(hdd_adapter_t *pAdapter)
1035{
1036 eHalStatus ret;
1037 tpSirGtkOffloadParams pGtkOffloadReqParams;
1038 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1039
1040 pGtkOffloadReqParams =
1041 &pHddStaCtx->gtkOffloadRequestParams.gtkOffloadReqParams;
1042
1043 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1044 (0 != memcmp(&pGtkOffloadReqParams->bssId,
1045 &pHddStaCtx->conn_info.bssId, WNI_CFG_BSSID_LEN)) &&
1046 (FALSE == pHddStaCtx->gtkOffloadRequestParams.requested))
1047 {
1048 /* Host driver has previously offloaded GTK rekey */
1049 ret = sme_GetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1050 wlan_hdd_cfg80211_update_replayCounterCallback,
1051 pAdapter, pAdapter->sessionId);
1052 if (eHAL_STATUS_SUCCESS != ret)
1053 {
1054 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1055 "%s: sme_GetGTKOffload failed, returned %d",
1056 __func__, ret);
1057 }
1058 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1059 "%s: sme_GetGTKOffload successfull", __func__);
1060
1061 /* Sending GTK offload dissable */
1062 pGtkOffloadReqParams->ulFlags = GTK_OFFLOAD_DISABLE;
1063 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1064 pGtkOffloadReqParams, pAdapter->sessionId);
1065
1066 if (eHAL_STATUS_SUCCESS != ret)
1067 {
1068 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1069 "%s: failed to dissable GTK offload, returned %d",
1070 __func__, ret);
1071 }
1072 pHddStaCtx->gtkOffloadRequestParams.requested = FALSE;
1073 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1074 "%s: successfully dissabled GTK offload request to HAL",
1075 __func__);
1076 }
1077}
1078#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
Jeff Johnson295189b2012-06-20 16:38:30 -07001079
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001080void hdd_resume_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001081{
1082 hdd_context_t *pHddCtx = NULL;
1083 hdd_adapter_t *pAdapter = NULL;
1084 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1085 VOS_STATUS status;
1086 v_CONTEXT_t pVosContext = NULL;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001087
Jeff Johnson295189b2012-06-20 16:38:30 -07001088 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
1089
1090 //Get the global VOSS context.
1091 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1092 if(!pVosContext) {
1093 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1094 return;
1095 }
1096
1097 //Get the HDD context.
1098 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1099
1100 if(!pHddCtx) {
1101 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1102 return;
1103 }
1104
1105 if (pHddCtx->isLogpInProgress) {
1106 hddLog(VOS_TRACE_LEVEL_INFO,
1107 "%s: Ignore resume wlan, LOGP in progress!", __func__);
1108 return;
1109 }
1110
Jeff Johnson295189b2012-06-20 16:38:30 -07001111 pHddCtx->hdd_wlan_suspended = FALSE;
1112 /*loop through all adapters. Concurrency */
1113 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1114
1115 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1116 {
1117 pAdapter = pAdapterNode->pAdapter;
1118 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001119 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001120 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001121 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001122 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1123 pAdapterNode = pNext;
1124 continue;
1125 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301126
1127#ifdef WLAN_FEATURE_GTK_OFFLOAD
1128 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
1129 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
1130 {
1131 wlan_hdd_update_and_dissable_gtk_offload(pAdapter);
1132 }
1133#endif
1134
Jeff Johnson295189b2012-06-20 16:38:30 -07001135#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1136 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP)
1137 {
1138 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__);
1139 hdd_exit_deep_sleep(pAdapter);
1140 }
1141#endif
1142
1143 if(pHddCtx->hdd_ignore_dtim_enabled == TRUE)
1144 {
1145 /*Switch back to DTIM 1*/
1146 tSirSetPowerParamsReq powerRequest = { 0 };
1147
1148 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
1149 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07001150 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001151
1152 /*Disabled ModulatedDTIM if enabled on suspend*/
1153 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1154 powerRequest.uDTIMPeriod = 0;
1155
1156 /* Update ignoreDTIM and ListedInterval in CFG with default values */
1157 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1158 NULL, eANI_BOOLEAN_FALSE);
1159 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1160 NULL, eANI_BOOLEAN_FALSE);
1161
1162 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1163 "Switch to DTIM%d \n",powerRequest.uListenInterval);
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08001164 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001165
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301166 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
1167 {
1168 /* put the device into full power */
1169 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001170
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301171 /* put the device back into BMPS */
1172 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
Jeff Johnson295189b2012-06-20 16:38:30 -07001173
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301174 pHddCtx->hdd_ignore_dtim_enabled = FALSE;
1175 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001176 }
1177
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301178 hdd_conf_resume_ind(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001179 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1180 pAdapterNode = pNext;
1181 }
1182
1183#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1184 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY)
1185 {
1186 hdd_exit_standby(pHddCtx);
1187 }
1188#endif
1189
Jeff Johnson295189b2012-06-20 16:38:30 -07001190 return;
1191}
1192
Jeff Johnson295189b2012-06-20 16:38:30 -07001193VOS_STATUS hdd_wlan_reset_initialization(void)
1194{
Jeff Johnson295189b2012-06-20 16:38:30 -07001195 v_CONTEXT_t pVosContext = NULL;
1196
1197 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1198
1199 //Get the global VOSS context.
1200 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1201 if(!pVosContext)
1202 {
1203 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1204 return VOS_STATUS_E_FAILURE;
1205 }
1206
1207 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__);
1208
1209 // Prevent the phone from going to sleep
1210 hdd_prevent_suspend();
1211
Jeff Johnson295189b2012-06-20 16:38:30 -07001212 return VOS_STATUS_SUCCESS;
1213}
1214
1215
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001216/*
1217 * Based on the ioctl command recieved by HDD, put WLAN driver
1218 * into the quiet mode. This is the same as the early suspend
1219 * notification that driver used to listen
1220 */
1221void hdd_set_wlan_suspend_mode(bool suspend)
Jeff Johnson295189b2012-06-20 16:38:30 -07001222{
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001223 if (suspend)
1224 hdd_suspend_wlan();
1225 else
1226 hdd_resume_wlan();
Jeff Johnson295189b2012-06-20 16:38:30 -07001227}
1228
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001229static void hdd_ssr_timer_init(void)
1230{
1231 init_timer(&ssr_timer);
1232}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001233
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001234static void hdd_ssr_timer_del(void)
1235{
1236 del_timer(&ssr_timer);
1237 ssr_timer_started = false;
1238}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001239
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001240static void hdd_ssr_timer_cb(unsigned long data)
1241{
1242 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD SSR timer expired", __func__);
1243 VOS_BUG(0);
1244}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001245
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001246static void hdd_ssr_timer_start(int msec)
1247{
1248 if(ssr_timer_started)
1249 {
1250 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: trying to start SSR timer when it's running"
1251 ,__func__);
1252 }
1253 ssr_timer.expires = jiffies + msecs_to_jiffies(msec);
1254 ssr_timer.function = hdd_ssr_timer_cb;
1255 add_timer(&ssr_timer);
1256 ssr_timer_started = true;
1257}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001258
Jeff Johnson295189b2012-06-20 16:38:30 -07001259/* the HDD interface to WLAN driver shutdown,
1260 * the primary shutdown function in SSR
1261 */
1262VOS_STATUS hdd_wlan_shutdown(void)
1263{
1264 VOS_STATUS vosStatus;
1265 v_CONTEXT_t pVosContext = NULL;
1266 hdd_context_t *pHddCtx = NULL;
1267 pVosSchedContext vosSchedContext = NULL;
1268
1269 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__);
1270
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001271 /* if re-init never happens, then do SSR1 */
1272 hdd_ssr_timer_init();
1273 hdd_ssr_timer_start(HDD_SSR_BRING_UP_TIME);
1274
Jeff Johnson295189b2012-06-20 16:38:30 -07001275 /* Get the global VOSS context. */
1276 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1277 if(!pVosContext) {
1278 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1279 return VOS_STATUS_E_FAILURE;
1280 }
1281 /* Get the HDD context. */
1282 pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1283 if(!pHddCtx) {
1284 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1285 return VOS_STATUS_E_FAILURE;
1286 }
1287 hdd_reset_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001288 /* DeRegister with platform driver as client for Suspend/Resume */
1289 vosStatus = hddDeregisterPmOps(pHddCtx);
1290 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1291 {
1292 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
1293 }
1294
1295 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
1296 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1297 {
1298 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
1299 }
1300
1301 /* Disable IMPS/BMPS as we do not want the device to enter any power
1302 * save mode on its own during reset sequence
1303 */
1304 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1305 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1306 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1307
1308 vosSchedContext = get_vos_sched_ctxt();
1309
1310 /* Wakeup all driver threads */
1311 if(TRUE == pHddCtx->isMcThreadSuspended){
1312 complete(&vosSchedContext->ResumeMcEvent);
1313 pHddCtx->isMcThreadSuspended= FALSE;
1314 }
1315 if(TRUE == pHddCtx->isTxThreadSuspended){
1316 complete(&vosSchedContext->ResumeTxEvent);
1317 pHddCtx->isTxThreadSuspended= FALSE;
1318 }
1319 if(TRUE == pHddCtx->isRxThreadSuspended){
1320 complete(&vosSchedContext->ResumeRxEvent);
1321 pHddCtx->isRxThreadSuspended= FALSE;
1322 }
1323 /* Reset the Suspend Variable */
1324 pHddCtx->isWlanSuspended = FALSE;
1325
1326 /* Stop all the threads; we do not want any messages to be a processed,
1327 * any more and the best way to ensure that is to terminate the threads
1328 * gracefully.
1329 */
1330 /* Wait for MC to exit */
1331 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
1332 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
1333 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
1334 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
1335 wait_for_completion_interruptible(&vosSchedContext->McShutdown);
1336
1337 /* Wait for TX to exit */
1338 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
1339 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
1340 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
1341 wake_up_interruptible(&vosSchedContext->txWaitQueue);
1342 wait_for_completion_interruptible(&vosSchedContext->TxShutdown);
1343
1344 /* Wait for RX to exit */
1345 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
1346 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
1347 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
1348 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
1349 wait_for_completion_interruptible(&vosSchedContext->RxShutdown);
1350
1351#ifdef WLAN_BTAMP_FEATURE
1352 vosStatus = WLANBAP_Stop(pVosContext);
1353 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1354 {
1355 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1356 "%s: Failed to stop BAP",__func__);
1357 }
1358#endif //WLAN_BTAMP_FEATURE
1359 vosStatus = vos_wda_shutdown(pVosContext);
1360 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1361
1362 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
1363 /* Stop SME - Cannot invoke vos_stop as vos_stop relies
1364 * on threads being running to process the SYS Stop
1365 */
1366 vosStatus = sme_Stop(pHddCtx->hHal, TRUE);
1367 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1368
1369 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
1370 /* Stop MAC (PE and HAL) */
1371 vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
1372 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1373
1374 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
1375 /* Stop TL */
1376 vosStatus = WLANTL_Stop(pVosContext);
1377 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1378
Jeff Johnson295189b2012-06-20 16:38:30 -07001379 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001380 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__);
1381 /* Clean up message queues of TX and MC thread */
1382 vos_sched_flush_mc_mqs(vosSchedContext);
1383 vos_sched_flush_tx_mqs(vosSchedContext);
1384 vos_sched_flush_rx_mqs(vosSchedContext);
1385
1386 /* Deinit all the TX and MC queues */
1387 vos_sched_deinit_mqs(vosSchedContext);
1388 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__);
1389
1390 /* shutdown VOSS */
1391 vos_shutdown(pVosContext);
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05301392
1393 /*mac context has already been released in mac_close call
1394 so setting it to NULL in hdd context*/
1395 pHddCtx->hHal = (tHalHandle)NULL;
1396
Jeff Johnson295189b2012-06-20 16:38:30 -07001397 if (free_riva_power_on_lock("wlan"))
1398 {
1399 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
1400 __func__);
1401 }
1402 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete"
1403 ,__func__);
1404 return VOS_STATUS_SUCCESS;
1405}
1406
1407
1408
1409/* the HDD interface to WLAN driver re-init.
1410 * This is called to initialize/start WLAN driver after a shutdown.
1411 */
1412VOS_STATUS hdd_wlan_re_init(void)
1413{
1414 VOS_STATUS vosStatus;
1415 v_CONTEXT_t pVosContext = NULL;
1416 hdd_context_t *pHddCtx = NULL;
1417 eHalStatus halStatus;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07001418#ifdef HAVE_WCNSS_CAL_DOWNLOAD
1419 int max_retries = 0;
1420#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001421#ifdef WLAN_BTAMP_FEATURE
1422 hdd_config_t *pConfig = NULL;
1423 WLANBAP_ConfigType btAmpConfig;
1424#endif
1425
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001426 hdd_ssr_timer_del();
Jeff Johnson295189b2012-06-20 16:38:30 -07001427 hdd_prevent_suspend();
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001428
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07001429#ifdef HAVE_WCNSS_CAL_DOWNLOAD
1430 /* wait until WCNSS driver downloads NV */
1431 while (!wcnss_device_ready() && 5 >= ++max_retries) {
1432 msleep(1000);
1433 }
1434 if (max_retries >= 5) {
1435 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
1436 goto err_re_init;
1437 }
1438#endif
1439
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001440 /* The driver should always be initialized in STA mode after SSR */
1441 hdd_set_conparam(0);
1442
Jeff Johnson295189b2012-06-20 16:38:30 -07001443 /* Re-open VOSS, it is a re-open b'se control transport was never closed. */
1444 vosStatus = vos_open(&pVosContext, 0);
1445 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1446 {
1447 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
1448 goto err_re_init;
1449 }
1450
1451 /* Get the HDD context. */
1452 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1453 if(!pHddCtx)
1454 {
1455 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1456 goto err_vosclose;
1457 }
1458
1459 /* Save the hal context in Adapter */
1460 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
1461 if ( NULL == pHddCtx->hHal )
1462 {
1463 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
1464 goto err_vosclose;
1465 }
1466
1467 /* Set the SME configuration parameters. */
1468 vosStatus = hdd_set_sme_config(pHddCtx);
1469 if ( VOS_STATUS_SUCCESS != vosStatus )
1470 {
1471 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
1472 goto err_vosclose;
1473 }
1474
1475 /* Initialize the WMM module */
1476 vosStatus = hdd_wmm_init(pHddCtx);
1477 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
1478 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001479 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001480 goto err_vosclose;
1481 }
1482
1483 vosStatus = vos_preStart( pHddCtx->pvosContext );
1484 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1485 {
1486 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
1487 goto err_vosclose;
1488 }
1489
1490 /* In the integrated architecture we update the configuration from
1491 the INI file and from NV before vOSS has been started so that
1492 the final contents are available to send down to the cCPU */
1493 /* Apply the cfg.ini to cfg.dat */
1494 if (FALSE == hdd_update_config_dat(pHddCtx))
1495 {
1496 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
1497 goto err_vosclose;
1498 }
1499
1500 /* Set the MAC Address, currently this is used by HAL to add self sta.
1501 * Remove this once self sta is added as part of session open. */
1502 halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID,
1503 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
1504 sizeof(pHddCtx->cfg_ini->intfMacAddr[0]));
1505 if (!HAL_STATUS_SUCCESS(halStatus))
1506 {
1507 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
1508 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus);
1509 goto err_vosclose;
1510 }
1511
1512 /* Start VOSS which starts up the SME/MAC/HAL modules and everything else
1513 Note: Firmware image will be read and downloaded inside vos_start API */
1514 vosStatus = vos_start( pVosContext );
1515 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1516 {
1517 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
1518 goto err_vosclose;
1519 }
1520
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07001521 /* Exchange capability info between Host and FW and also get versioning info from FW */
1522 hdd_exchange_version_and_caps(pHddCtx);
1523
Jeff Johnson295189b2012-06-20 16:38:30 -07001524 vosStatus = hdd_post_voss_start_config( pHddCtx );
1525 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1526 {
1527 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
1528 __func__);
1529 goto err_vosstop;
1530 }
1531
1532#ifdef WLAN_BTAMP_FEATURE
1533 vosStatus = WLANBAP_Open(pVosContext);
1534 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1535 {
1536 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1537 "%s: Failed to open BAP",__func__);
1538 goto err_vosstop;
1539 }
1540 vosStatus = BSL_Init(pVosContext);
1541 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1542 {
1543 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1544 "%s: Failed to Init BSL",__func__);
1545 goto err_bap_close;
1546 }
1547 vosStatus = WLANBAP_Start(pVosContext);
1548 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1549 {
1550 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1551 "%s: Failed to start TL",__func__);
1552 goto err_bap_close;
1553 }
1554 pConfig = pHddCtx->cfg_ini;
1555 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
1556 vosStatus = WLANBAP_SetConfig(&btAmpConfig);
1557#endif //WLAN_BTAMP_FEATURE
1558
1559 /* Restart all adapters */
1560 hdd_start_all_adapters(pHddCtx);
1561 pHddCtx->isLogpInProgress = FALSE;
1562 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001563 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001564
1565 /* Register with platform driver as client for Suspend/Resume */
1566 vosStatus = hddRegisterPmOps(pHddCtx);
1567 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1568 {
1569 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
1570 goto err_bap_stop;
1571 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001572 /* Allow the phone to go to sleep */
1573 hdd_allow_suspend();
1574 /* register for riva power on lock */
1575 if (req_riva_power_on_lock("wlan"))
1576 {
1577 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
1578 __func__);
1579 goto err_unregister_pmops;
1580 }
1581 goto success;
1582
1583err_unregister_pmops:
1584 hddDeregisterPmOps(pHddCtx);
1585
1586err_bap_stop:
Jeff Johnson32d95a32012-09-10 13:15:23 -07001587#ifdef CONFIG_HAS_EARLYSUSPEND
1588 hdd_unregister_mcast_bcast_filter(pHddCtx);
1589#endif
1590 hdd_close_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001591#ifdef WLAN_BTAMP_FEATURE
Jeff Johnson32d95a32012-09-10 13:15:23 -07001592 WLANBAP_Stop(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07001593#endif
1594
1595#ifdef WLAN_BTAMP_FEATURE
1596err_bap_close:
1597 WLANBAP_Close(pVosContext);
1598#endif
1599
1600err_vosstop:
1601 vos_stop(pVosContext);
1602
1603err_vosclose:
1604 vos_close(pVosContext);
1605 vos_sched_close(pVosContext);
1606 if (pHddCtx)
1607 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001608 /* Unregister the Net Device Notifier */
1609 unregister_netdevice_notifier(&hdd_netdev_notifier);
1610 /* Clean up HDD Nlink Service */
1611 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1612 nl_srv_exit();
Jeff Johnson295189b2012-06-20 16:38:30 -07001613 /* Free up dynamically allocated members inside HDD Adapter */
1614 kfree(pHddCtx->cfg_ini);
1615 pHddCtx->cfg_ini= NULL;
1616
Jeff Johnson295189b2012-06-20 16:38:30 -07001617 wiphy_unregister(pHddCtx->wiphy);
1618 wiphy_free(pHddCtx->wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07001619 }
1620 vos_preClose(&pVosContext);
1621
1622#ifdef MEMORY_DEBUG
1623 vos_mem_exit();
1624#endif
1625
1626err_re_init:
1627 /* Allow the phone to go to sleep */
1628 hdd_allow_suspend();
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001629 return -EPERM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001630
1631success:
1632 /* Trigger replay of BTC events */
1633 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1634 return VOS_STATUS_SUCCESS;
1635}