blob: 7984a354144c789bc7b2078e23084a6df9a25689 [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 Nakkala0f276812013-02-24 14:45:51 +0530746 if (pHddCtx->cfg_ini->fhostArpOffload)
Jeff Johnson295189b2012-06-20 16:38:30 -0700747 {
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530748 vstatus = hdd_conf_hostarpoffload(pAdapter, FALSE);
749 if (!VOS_IS_STATUS_SUCCESS(vstatus))
750 {
751 hddLog(VOS_TRACE_LEVEL_INFO, "%s:Failed to disable ARPOFFLOAD "
752 "Feature %d\n", __func__, vstatus);
753 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700754 }
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530755 if (pHddCtx->dynamic_mcbc_filter.enableSuspend)
756 {
757 wlanResumeParam->configuredMcstBcstFilterSetting =
758 pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend;
759 }
760 else
761 {
762 wlanResumeParam->configuredMcstBcstFilterSetting =
763 pHddCtx->cfg_ini->mcastBcastFilterSetting;
764 }
Chilam Ngc4244af2013-04-01 15:37:32 -0700765 halStatus = sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam);
766 if (eHAL_STATUS_SUCCESS != halStatus)
767 vos_mem_free(wlanResumeParam);
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530768 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700769 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700770
Chilam Ngc4244af2013-04-01 15:37:32 -0700771
Jeff Johnson295189b2012-06-20 16:38:30 -0700772#ifdef WLAN_FEATURE_PACKET_FILTERING
773 if (pHddCtx->cfg_ini->isMcAddrListFilter)
774 {
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530775 /*Multicast addr filtering is enabled*/
776 if (pAdapter->mc_addr_list.isFilterApplied)
Jeff Johnson295189b2012-06-20 16:38:30 -0700777 {
778 /*Filter applied during suspend mode*/
779 /*Clear it here*/
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530780 wlan_hdd_set_mc_addr_list(pAdapter, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700781 }
782 }
783#endif
784}
Jeff Johnson295189b2012-06-20 16:38:30 -0700785
Jeff Johnson295189b2012-06-20 16:38:30 -0700786//Suspend routine registered with Android OS
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800787void hdd_suspend_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -0700788{
789 hdd_context_t *pHddCtx = NULL;
790 v_CONTEXT_t pVosContext = NULL;
791
792 hdd_adapter_t *pAdapter = NULL;
793 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
794 VOS_STATUS status;
Jeff Johnsonbc676b42013-02-14 16:04:08 -0800795
Jeff Johnson295189b2012-06-20 16:38:30 -0700796 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__);
797
798 //Get the global VOSS context.
799 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
800 if(!pVosContext) {
801 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
802 return;
803 }
804
805 //Get the HDD context.
806 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
807
808 if(!pHddCtx) {
809 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
810 return;
811 }
812
813 if (pHddCtx->isLogpInProgress) {
814 hddLog(VOS_TRACE_LEVEL_ERROR,
815 "%s: Ignore suspend wlan, LOGP in progress!", __func__);
816 return;
817 }
818
Jeff Johnson295189b2012-06-20 16:38:30 -0700819 /*loop through all adapters. TBD fix for Concurrency */
820 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
821 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
822 {
823 pAdapter = pAdapterNode->pAdapter;
824 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -0700825 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -0700826 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
827
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -0700828 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -0700829 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
830 pAdapterNode = pNext;
831 continue;
832 }
833
834#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
835 if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
836 {
837 //stop the interface before putting the chip to standby
838 netif_tx_disable(pAdapter->dev);
839 netif_carrier_off(pAdapter->dev);
840 }
841 else if (pHddCtx->cfg_ini->nEnableSuspend ==
842 WLAN_MAP_SUSPEND_TO_DEEP_SLEEP)
843 {
844 //Execute deep sleep procedure
845 hdd_enter_deep_sleep(pHddCtx, pAdapter);
846 }
847#endif
848
Jeff Johnsone7245742012-09-05 17:12:55 -0700849 //Apply Dynamic Dtim For P2P
850 //Only if ignoreDynamicDtimInP2pMode is not set in ini
Jeff Johnson295189b2012-06-20 16:38:30 -0700851 if((pHddCtx->cfg_ini->enableDynamicDTIM ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700852 pHddCtx->cfg_ini->enableModulatedDTIM) &&
853 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
854 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
855 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
Jeff Johnson295189b2012-06-20 16:38:30 -0700856 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
857 (eConnectionState_Associated ==
858 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
859 (pHddCtx->cfg_ini->fIsBmpsEnabled))
860 {
861 tSirSetPowerParamsReq powerRequest = { 0 };
862
863 powerRequest.uIgnoreDTIM = 1;
864
865 /*Back up the actual values from CFG */
866 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM,
867 &pHddCtx->hdd_actual_ignore_DTIM_value);
868 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL,
869 &pHddCtx->hdd_actual_LI_value);
870
871 if(pHddCtx->cfg_ini->enableModulatedDTIM)
872 {
873 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
874 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
875 }
876 else
877 {
878 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
879 }
880
881 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
882 *specified during Enter/Exit BMPS when LCD off*/
883 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
884 NULL, eANI_BOOLEAN_FALSE);
885 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
886 NULL, eANI_BOOLEAN_FALSE);
887
888 /* switch to the DTIM specified in cfg.ini */
889 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
890 "Switch to DTIM%d \n", powerRequest.uListenInterval);
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -0800891 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700892
893 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
894 {
895 /* put the device into full power */
896 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
897
898 /* put the device back into BMPS */
899 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
900
901 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
902 }
903 }
904
Jeff Johnson295189b2012-06-20 16:38:30 -0700905 /*Suspend notification sent down to driver*/
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530906 hdd_conf_suspend_ind(pHddCtx, pAdapter);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +0530907
908#ifdef WLAN_FEATURE_GTK_OFFLOAD
909 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
910 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
911 {
912 eHalStatus ret;
913 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
914 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
915 (TRUE == pHddStaCtx->gtkOffloadRequestParams.requested))
916 {
917 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
918 &pHddStaCtx->gtkOffloadRequestParams.gtkOffloadReqParams,
919 pAdapter->sessionId);
920 if (eHAL_STATUS_SUCCESS != ret)
921 {
922 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
923 "%s: sme_SetGTKOffload failed, returned %d",
924 __func__, ret);
925 }
926 pHddStaCtx->gtkOffloadRequestParams.requested = FALSE;
927 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
928 "%s: sme_SetGTKOffload successfull",
929 __func__);
930 }
931 }
932#endif
933
Jeff Johnson295189b2012-06-20 16:38:30 -0700934 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
935 pAdapterNode = pNext;
936 }
937 pHddCtx->hdd_wlan_suspended = TRUE;
938
939#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
940 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
941 {
942 hdd_enter_standby(pHddCtx);
943 }
944#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700945
946 return;
947}
948
949static void hdd_PowerStateChangedCB
950(
951 v_PVOID_t callbackContext,
952 tPmcState newState
953)
954{
955 hdd_context_t *pHddCtx = callbackContext;
956
957 /* if the driver was not in BMPS during early suspend,
958 * the dynamic DTIM is now updated at Riva */
959 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended
960 && pHddCtx->cfg_ini->enableDynamicDTIM
961 && (pHddCtx->hdd_ignore_dtim_enabled == FALSE))
962 {
963 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
964 }
965 spin_lock(&pHddCtx->filter_lock);
Gopichand Nakkalac1b11522013-03-25 15:25:33 +0530966 if((newState == BMPS) && pHddCtx->hdd_wlan_suspended) {
Jeff Johnson295189b2012-06-20 16:38:30 -0700967 spin_unlock(&pHddCtx->filter_lock);
968 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700969 if(pHddCtx->hdd_mcastbcast_filter_set != TRUE)
970 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__);
971 }
972 else
973 spin_unlock(&pHddCtx->filter_lock);
974}
975
976
977
978void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx)
979{
980 v_CONTEXT_t pVosContext;
981 tHalHandle smeContext;
982
983 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
984 if (NULL == pVosContext)
985 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700986 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700987 return;
988 }
989 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
990 if (NULL == smeContext)
991 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700992 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700993 return;
994 }
995
996 spin_lock_init(&pHddCtx->filter_lock);
997 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
998 pHddCtx->cfg_ini->nEnableSuspend)
999 {
1000 pmcRegisterDeviceStateUpdateInd(smeContext,
1001 hdd_PowerStateChangedCB, pHddCtx);
1002 }
1003}
1004
1005void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx)
1006{
1007 v_CONTEXT_t pVosContext;
1008 tHalHandle smeContext;
1009
1010 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1011 if (NULL == pVosContext)
1012 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001013 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001014 return;
1015 }
1016 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1017 if (NULL == smeContext)
1018 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001019 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001020 return;
1021 }
1022
1023 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1024 pHddCtx->cfg_ini->nEnableSuspend)
1025 {
1026 pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB);
1027 }
1028}
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301029#ifdef WLAN_FEATURE_GTK_OFFLOAD
1030void wlan_hdd_update_and_dissable_gtk_offload(hdd_adapter_t *pAdapter)
1031{
1032 eHalStatus ret;
1033 tpSirGtkOffloadParams pGtkOffloadReqParams;
1034 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1035
1036 pGtkOffloadReqParams =
1037 &pHddStaCtx->gtkOffloadRequestParams.gtkOffloadReqParams;
1038
1039 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1040 (0 != memcmp(&pGtkOffloadReqParams->bssId,
1041 &pHddStaCtx->conn_info.bssId, WNI_CFG_BSSID_LEN)) &&
1042 (FALSE == pHddStaCtx->gtkOffloadRequestParams.requested))
1043 {
1044 /* Host driver has previously offloaded GTK rekey */
1045 ret = sme_GetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1046 wlan_hdd_cfg80211_update_replayCounterCallback,
1047 pAdapter, pAdapter->sessionId);
1048 if (eHAL_STATUS_SUCCESS != ret)
1049 {
1050 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1051 "%s: sme_GetGTKOffload failed, returned %d",
1052 __func__, ret);
1053 }
1054 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1055 "%s: sme_GetGTKOffload successfull", __func__);
1056
1057 /* Sending GTK offload dissable */
1058 pGtkOffloadReqParams->ulFlags = GTK_OFFLOAD_DISABLE;
1059 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1060 pGtkOffloadReqParams, pAdapter->sessionId);
1061
1062 if (eHAL_STATUS_SUCCESS != ret)
1063 {
1064 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1065 "%s: failed to dissable GTK offload, returned %d",
1066 __func__, ret);
1067 }
1068 pHddStaCtx->gtkOffloadRequestParams.requested = FALSE;
1069 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1070 "%s: successfully dissabled GTK offload request to HAL",
1071 __func__);
1072 }
1073}
1074#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
Jeff Johnson295189b2012-06-20 16:38:30 -07001075
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001076void hdd_resume_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001077{
1078 hdd_context_t *pHddCtx = NULL;
1079 hdd_adapter_t *pAdapter = NULL;
1080 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1081 VOS_STATUS status;
1082 v_CONTEXT_t pVosContext = NULL;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001083
Jeff Johnson295189b2012-06-20 16:38:30 -07001084 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
1085
1086 //Get the global VOSS context.
1087 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1088 if(!pVosContext) {
1089 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1090 return;
1091 }
1092
1093 //Get the HDD context.
1094 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1095
1096 if(!pHddCtx) {
1097 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1098 return;
1099 }
1100
1101 if (pHddCtx->isLogpInProgress) {
1102 hddLog(VOS_TRACE_LEVEL_INFO,
1103 "%s: Ignore resume wlan, LOGP in progress!", __func__);
1104 return;
1105 }
1106
Jeff Johnson295189b2012-06-20 16:38:30 -07001107 pHddCtx->hdd_wlan_suspended = FALSE;
1108 /*loop through all adapters. Concurrency */
1109 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1110
1111 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1112 {
1113 pAdapter = pAdapterNode->pAdapter;
1114 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001115 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001116 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001117 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001118 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1119 pAdapterNode = pNext;
1120 continue;
1121 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301122
1123#ifdef WLAN_FEATURE_GTK_OFFLOAD
1124 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
1125 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
1126 {
1127 wlan_hdd_update_and_dissable_gtk_offload(pAdapter);
1128 }
1129#endif
1130
Jeff Johnson295189b2012-06-20 16:38:30 -07001131#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1132 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP)
1133 {
1134 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__);
1135 hdd_exit_deep_sleep(pAdapter);
1136 }
1137#endif
1138
1139 if(pHddCtx->hdd_ignore_dtim_enabled == TRUE)
1140 {
1141 /*Switch back to DTIM 1*/
1142 tSirSetPowerParamsReq powerRequest = { 0 };
1143
1144 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
1145 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
1146
1147 /*Disabled ModulatedDTIM if enabled on suspend*/
1148 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1149 powerRequest.uDTIMPeriod = 0;
1150
1151 /* Update ignoreDTIM and ListedInterval in CFG with default values */
1152 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1153 NULL, eANI_BOOLEAN_FALSE);
1154 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1155 NULL, eANI_BOOLEAN_FALSE);
1156
1157 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1158 "Switch to DTIM%d \n",powerRequest.uListenInterval);
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08001159 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001160
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301161 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
1162 {
1163 /* put the device into full power */
1164 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001165
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301166 /* put the device back into BMPS */
1167 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
Jeff Johnson295189b2012-06-20 16:38:30 -07001168
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301169 pHddCtx->hdd_ignore_dtim_enabled = FALSE;
1170 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001171 }
1172
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301173 hdd_conf_resume_ind(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001174 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1175 pAdapterNode = pNext;
1176 }
1177
1178#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1179 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY)
1180 {
1181 hdd_exit_standby(pHddCtx);
1182 }
1183#endif
1184
Jeff Johnson295189b2012-06-20 16:38:30 -07001185 return;
1186}
1187
Jeff Johnson295189b2012-06-20 16:38:30 -07001188VOS_STATUS hdd_wlan_reset_initialization(void)
1189{
Jeff Johnson295189b2012-06-20 16:38:30 -07001190 v_CONTEXT_t pVosContext = NULL;
1191
1192 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1193
1194 //Get the global VOSS context.
1195 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1196 if(!pVosContext)
1197 {
1198 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1199 return VOS_STATUS_E_FAILURE;
1200 }
1201
1202 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__);
1203
1204 // Prevent the phone from going to sleep
1205 hdd_prevent_suspend();
1206
Jeff Johnson295189b2012-06-20 16:38:30 -07001207 return VOS_STATUS_SUCCESS;
1208}
1209
1210
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001211/*
1212 * Based on the ioctl command recieved by HDD, put WLAN driver
1213 * into the quiet mode. This is the same as the early suspend
1214 * notification that driver used to listen
1215 */
1216void hdd_set_wlan_suspend_mode(bool suspend)
Jeff Johnson295189b2012-06-20 16:38:30 -07001217{
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001218 if (suspend)
1219 hdd_suspend_wlan();
1220 else
1221 hdd_resume_wlan();
Jeff Johnson295189b2012-06-20 16:38:30 -07001222}
1223
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001224static void hdd_ssr_timer_init(void)
1225{
1226 init_timer(&ssr_timer);
1227}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001228
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001229static void hdd_ssr_timer_del(void)
1230{
1231 del_timer(&ssr_timer);
1232 ssr_timer_started = false;
1233}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001234
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001235static void hdd_ssr_timer_cb(unsigned long data)
1236{
1237 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD SSR timer expired", __func__);
1238 VOS_BUG(0);
1239}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001240
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001241static void hdd_ssr_timer_start(int msec)
1242{
1243 if(ssr_timer_started)
1244 {
1245 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: trying to start SSR timer when it's running"
1246 ,__func__);
1247 }
1248 ssr_timer.expires = jiffies + msecs_to_jiffies(msec);
1249 ssr_timer.function = hdd_ssr_timer_cb;
1250 add_timer(&ssr_timer);
1251 ssr_timer_started = true;
1252}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001253
Jeff Johnson295189b2012-06-20 16:38:30 -07001254/* the HDD interface to WLAN driver shutdown,
1255 * the primary shutdown function in SSR
1256 */
1257VOS_STATUS hdd_wlan_shutdown(void)
1258{
1259 VOS_STATUS vosStatus;
1260 v_CONTEXT_t pVosContext = NULL;
1261 hdd_context_t *pHddCtx = NULL;
1262 pVosSchedContext vosSchedContext = NULL;
1263
1264 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__);
1265
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001266 /* if re-init never happens, then do SSR1 */
1267 hdd_ssr_timer_init();
1268 hdd_ssr_timer_start(HDD_SSR_BRING_UP_TIME);
1269
Jeff Johnson295189b2012-06-20 16:38:30 -07001270 /* Get the global VOSS context. */
1271 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1272 if(!pVosContext) {
1273 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1274 return VOS_STATUS_E_FAILURE;
1275 }
1276 /* Get the HDD context. */
1277 pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1278 if(!pHddCtx) {
1279 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1280 return VOS_STATUS_E_FAILURE;
1281 }
1282 hdd_reset_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001283 /* DeRegister with platform driver as client for Suspend/Resume */
1284 vosStatus = hddDeregisterPmOps(pHddCtx);
1285 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1286 {
1287 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
1288 }
1289
1290 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
1291 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1292 {
1293 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
1294 }
1295
1296 /* Disable IMPS/BMPS as we do not want the device to enter any power
1297 * save mode on its own during reset sequence
1298 */
1299 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1300 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1301 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1302
1303 vosSchedContext = get_vos_sched_ctxt();
1304
1305 /* Wakeup all driver threads */
1306 if(TRUE == pHddCtx->isMcThreadSuspended){
1307 complete(&vosSchedContext->ResumeMcEvent);
1308 pHddCtx->isMcThreadSuspended= FALSE;
1309 }
1310 if(TRUE == pHddCtx->isTxThreadSuspended){
1311 complete(&vosSchedContext->ResumeTxEvent);
1312 pHddCtx->isTxThreadSuspended= FALSE;
1313 }
1314 if(TRUE == pHddCtx->isRxThreadSuspended){
1315 complete(&vosSchedContext->ResumeRxEvent);
1316 pHddCtx->isRxThreadSuspended= FALSE;
1317 }
1318 /* Reset the Suspend Variable */
1319 pHddCtx->isWlanSuspended = FALSE;
1320
1321 /* Stop all the threads; we do not want any messages to be a processed,
1322 * any more and the best way to ensure that is to terminate the threads
1323 * gracefully.
1324 */
1325 /* Wait for MC to exit */
1326 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
1327 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
1328 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
1329 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
1330 wait_for_completion_interruptible(&vosSchedContext->McShutdown);
1331
1332 /* Wait for TX to exit */
1333 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
1334 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
1335 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
1336 wake_up_interruptible(&vosSchedContext->txWaitQueue);
1337 wait_for_completion_interruptible(&vosSchedContext->TxShutdown);
1338
1339 /* Wait for RX to exit */
1340 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
1341 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
1342 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
1343 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
1344 wait_for_completion_interruptible(&vosSchedContext->RxShutdown);
1345
1346#ifdef WLAN_BTAMP_FEATURE
1347 vosStatus = WLANBAP_Stop(pVosContext);
1348 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1349 {
1350 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1351 "%s: Failed to stop BAP",__func__);
1352 }
1353#endif //WLAN_BTAMP_FEATURE
1354 vosStatus = vos_wda_shutdown(pVosContext);
1355 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1356
1357 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
1358 /* Stop SME - Cannot invoke vos_stop as vos_stop relies
1359 * on threads being running to process the SYS Stop
1360 */
1361 vosStatus = sme_Stop(pHddCtx->hHal, TRUE);
1362 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1363
1364 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
1365 /* Stop MAC (PE and HAL) */
1366 vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
1367 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1368
1369 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
1370 /* Stop TL */
1371 vosStatus = WLANTL_Stop(pVosContext);
1372 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1373
Jeff Johnson295189b2012-06-20 16:38:30 -07001374 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001375 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__);
1376 /* Clean up message queues of TX and MC thread */
1377 vos_sched_flush_mc_mqs(vosSchedContext);
1378 vos_sched_flush_tx_mqs(vosSchedContext);
1379 vos_sched_flush_rx_mqs(vosSchedContext);
1380
1381 /* Deinit all the TX and MC queues */
1382 vos_sched_deinit_mqs(vosSchedContext);
1383 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__);
1384
1385 /* shutdown VOSS */
1386 vos_shutdown(pVosContext);
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05301387
1388 /*mac context has already been released in mac_close call
1389 so setting it to NULL in hdd context*/
1390 pHddCtx->hHal = (tHalHandle)NULL;
1391
Jeff Johnson295189b2012-06-20 16:38:30 -07001392 if (free_riva_power_on_lock("wlan"))
1393 {
1394 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
1395 __func__);
1396 }
1397 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete"
1398 ,__func__);
1399 return VOS_STATUS_SUCCESS;
1400}
1401
1402
1403
1404/* the HDD interface to WLAN driver re-init.
1405 * This is called to initialize/start WLAN driver after a shutdown.
1406 */
1407VOS_STATUS hdd_wlan_re_init(void)
1408{
1409 VOS_STATUS vosStatus;
1410 v_CONTEXT_t pVosContext = NULL;
1411 hdd_context_t *pHddCtx = NULL;
1412 eHalStatus halStatus;
1413#ifdef WLAN_BTAMP_FEATURE
1414 hdd_config_t *pConfig = NULL;
1415 WLANBAP_ConfigType btAmpConfig;
1416#endif
1417
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001418 hdd_ssr_timer_del();
Jeff Johnson295189b2012-06-20 16:38:30 -07001419 hdd_prevent_suspend();
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001420
1421 /* The driver should always be initialized in STA mode after SSR */
1422 hdd_set_conparam(0);
1423
Jeff Johnson295189b2012-06-20 16:38:30 -07001424 /* Re-open VOSS, it is a re-open b'se control transport was never closed. */
1425 vosStatus = vos_open(&pVosContext, 0);
1426 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1427 {
1428 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
1429 goto err_re_init;
1430 }
1431
1432 /* Get the HDD context. */
1433 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1434 if(!pHddCtx)
1435 {
1436 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1437 goto err_vosclose;
1438 }
1439
1440 /* Save the hal context in Adapter */
1441 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
1442 if ( NULL == pHddCtx->hHal )
1443 {
1444 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
1445 goto err_vosclose;
1446 }
1447
1448 /* Set the SME configuration parameters. */
1449 vosStatus = hdd_set_sme_config(pHddCtx);
1450 if ( VOS_STATUS_SUCCESS != vosStatus )
1451 {
1452 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
1453 goto err_vosclose;
1454 }
1455
1456 /* Initialize the WMM module */
1457 vosStatus = hdd_wmm_init(pHddCtx);
1458 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
1459 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001460 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001461 goto err_vosclose;
1462 }
1463
1464 vosStatus = vos_preStart( pHddCtx->pvosContext );
1465 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1466 {
1467 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
1468 goto err_vosclose;
1469 }
1470
1471 /* In the integrated architecture we update the configuration from
1472 the INI file and from NV before vOSS has been started so that
1473 the final contents are available to send down to the cCPU */
1474 /* Apply the cfg.ini to cfg.dat */
1475 if (FALSE == hdd_update_config_dat(pHddCtx))
1476 {
1477 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
1478 goto err_vosclose;
1479 }
1480
1481 /* Set the MAC Address, currently this is used by HAL to add self sta.
1482 * Remove this once self sta is added as part of session open. */
1483 halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID,
1484 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
1485 sizeof(pHddCtx->cfg_ini->intfMacAddr[0]));
1486 if (!HAL_STATUS_SUCCESS(halStatus))
1487 {
1488 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
1489 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus);
1490 goto err_vosclose;
1491 }
1492
1493 /* Start VOSS which starts up the SME/MAC/HAL modules and everything else
1494 Note: Firmware image will be read and downloaded inside vos_start API */
1495 vosStatus = vos_start( pVosContext );
1496 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1497 {
1498 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
1499 goto err_vosclose;
1500 }
1501
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07001502 /* Exchange capability info between Host and FW and also get versioning info from FW */
1503 hdd_exchange_version_and_caps(pHddCtx);
1504
Jeff Johnson295189b2012-06-20 16:38:30 -07001505 vosStatus = hdd_post_voss_start_config( pHddCtx );
1506 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1507 {
1508 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
1509 __func__);
1510 goto err_vosstop;
1511 }
1512
1513#ifdef WLAN_BTAMP_FEATURE
1514 vosStatus = WLANBAP_Open(pVosContext);
1515 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1516 {
1517 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1518 "%s: Failed to open BAP",__func__);
1519 goto err_vosstop;
1520 }
1521 vosStatus = BSL_Init(pVosContext);
1522 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1523 {
1524 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1525 "%s: Failed to Init BSL",__func__);
1526 goto err_bap_close;
1527 }
1528 vosStatus = WLANBAP_Start(pVosContext);
1529 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1530 {
1531 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1532 "%s: Failed to start TL",__func__);
1533 goto err_bap_close;
1534 }
1535 pConfig = pHddCtx->cfg_ini;
1536 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
1537 vosStatus = WLANBAP_SetConfig(&btAmpConfig);
1538#endif //WLAN_BTAMP_FEATURE
1539
1540 /* Restart all adapters */
1541 hdd_start_all_adapters(pHddCtx);
1542 pHddCtx->isLogpInProgress = FALSE;
1543 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001544 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001545
1546 /* Register with platform driver as client for Suspend/Resume */
1547 vosStatus = hddRegisterPmOps(pHddCtx);
1548 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1549 {
1550 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
1551 goto err_bap_stop;
1552 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001553 /* Allow the phone to go to sleep */
1554 hdd_allow_suspend();
1555 /* register for riva power on lock */
1556 if (req_riva_power_on_lock("wlan"))
1557 {
1558 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
1559 __func__);
1560 goto err_unregister_pmops;
1561 }
1562 goto success;
1563
1564err_unregister_pmops:
1565 hddDeregisterPmOps(pHddCtx);
1566
1567err_bap_stop:
Jeff Johnson32d95a32012-09-10 13:15:23 -07001568#ifdef CONFIG_HAS_EARLYSUSPEND
1569 hdd_unregister_mcast_bcast_filter(pHddCtx);
1570#endif
1571 hdd_close_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001572#ifdef WLAN_BTAMP_FEATURE
Jeff Johnson32d95a32012-09-10 13:15:23 -07001573 WLANBAP_Stop(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07001574#endif
1575
1576#ifdef WLAN_BTAMP_FEATURE
1577err_bap_close:
1578 WLANBAP_Close(pVosContext);
1579#endif
1580
1581err_vosstop:
1582 vos_stop(pVosContext);
1583
1584err_vosclose:
1585 vos_close(pVosContext);
1586 vos_sched_close(pVosContext);
1587 if (pHddCtx)
1588 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001589 /* Unregister the Net Device Notifier */
1590 unregister_netdevice_notifier(&hdd_netdev_notifier);
1591 /* Clean up HDD Nlink Service */
1592 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1593 nl_srv_exit();
Jeff Johnson295189b2012-06-20 16:38:30 -07001594 /* Free up dynamically allocated members inside HDD Adapter */
1595 kfree(pHddCtx->cfg_ini);
1596 pHddCtx->cfg_ini= NULL;
1597
Jeff Johnson295189b2012-06-20 16:38:30 -07001598 wiphy_unregister(pHddCtx->wiphy);
1599 wiphy_free(pHddCtx->wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07001600 }
1601 vos_preClose(&pVosContext);
1602
1603#ifdef MEMORY_DEBUG
1604 vos_mem_exit();
1605#endif
1606
1607err_re_init:
1608 /* Allow the phone to go to sleep */
1609 hdd_allow_suspend();
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001610 return -EPERM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001611
1612success:
1613 /* Trigger replay of BTC events */
1614 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1615 return VOS_STATUS_SUCCESS;
1616}