blob: 30fb48d3cd8033cd246976dee1190086d987d578 [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);
Jeff Johnson295189b2012-06-20 16:38:30 -0700643 if(setfilter && (eHAL_STATUS_SUCCESS == halStatus))
644 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
645}
646
Jeff Johnson295189b2012-06-20 16:38:30 -0700647static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx,
648 hdd_adapter_t *pAdapter)
649{
650 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Madan Mohan Koyyalamudi51d87f72012-09-24 12:05:23 -0700651 VOS_STATUS vstatus = VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700652 tpSirWlanSuspendParam wlanSuspendParam =
653 vos_mem_malloc(sizeof(tSirWlanSuspendParam));
654
655 if(NULL == wlanSuspendParam)
656 {
657 hddLog(VOS_TRACE_LEVEL_FATAL,
658 "%s: vos_mem_alloc failed ", __func__);
659 return;
660 }
661
662 hddLog(VOS_TRACE_LEVEL_INFO,
663 "%s: send wlan suspend indication", __func__);
664
665 if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER))
666 {
667 if((pHddCtx->cfg_ini->fhostArpOffload) &&
668 (eConnectionState_Associated ==
669 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
670 {
Yathish9f22e662012-12-10 14:21:35 -0800671 vstatus = hdd_conf_hostarpoffload(pAdapter, TRUE);
Jeff Johnson43971f52012-07-17 12:26:56 -0700672 if (!VOS_IS_STATUS_SUCCESS(vstatus))
Jeff Johnson295189b2012-06-20 16:38:30 -0700673 {
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530674 hdd_mcbc_filter_modification(pHddCtx, FALSE,
675 &wlanSuspendParam->configuredMcstBcstFilterSetting);
Jeff Johnson295189b2012-06-20 16:38:30 -0700676 hddLog(VOS_TRACE_LEVEL_INFO,
677 "%s:Failed to enable ARPOFFLOAD Feature %d\n",
Jeff Johnson43971f52012-07-17 12:26:56 -0700678 __func__, vstatus);
Jeff Johnson295189b2012-06-20 16:38:30 -0700679 }
Jeff Johnson43971f52012-07-17 12:26:56 -0700680 else
681 {
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530682 hdd_mcbc_filter_modification(pHddCtx, TRUE,
683 &wlanSuspendParam->configuredMcstBcstFilterSetting);
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700684 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700685 }
686 else
687 {
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530688 hdd_mcbc_filter_modification(pHddCtx, FALSE,
689 &wlanSuspendParam->configuredMcstBcstFilterSetting);
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700690 if(pHddCtx->dynamic_mcbc_filter.enableCfg)
691 {
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700692 pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend =
Jeff Johnson43971f52012-07-17 12:26:56 -0700693 wlanSuspendParam->configuredMcstBcstFilterSetting;
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700694 }
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700695 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700696
697#ifdef WLAN_FEATURE_PACKET_FILTERING
698 if (pHddCtx->cfg_ini->isMcAddrListFilter)
699 {
700 /*Multicast addr list filter is enabled during suspend*/
701 if (((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
702 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT))
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530703 && pAdapter->mc_addr_list.mc_cnt
Jeff Johnson295189b2012-06-20 16:38:30 -0700704 && (eConnectionState_Associated ==
705 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
706 {
707 /*set the filter*/
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530708 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700709 }
710 }
711#endif
712 }
713
714 halStatus = sme_ConfigureSuspendInd(pHddCtx->hHal, wlanSuspendParam);
715 if(eHAL_STATUS_SUCCESS == halStatus)
716 {
717 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
718 }
719}
720
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530721static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700722{
Jeff Johnson43971f52012-07-17 12:26:56 -0700723 VOS_STATUS vstatus;
Yathish9f22e662012-12-10 14:21:35 -0800724 hdd_context_t* pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700725 tpSirWlanResumeParam wlanResumeParam =
726 vos_mem_malloc(sizeof(tSirWlanResumeParam));
727
728 if(NULL == wlanResumeParam)
729 {
730 hddLog(VOS_TRACE_LEVEL_FATAL,
731 "%s: vos_mem_alloc failed ", __func__);
732 return;
733 }
734
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530735 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700736 "%s: send wlan resume indication", __func__);
737
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530738 if (pHddCtx->hdd_mcastbcast_filter_set == TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -0700739 {
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530740 if (pHddCtx->cfg_ini->fhostArpOffload)
Jeff Johnson295189b2012-06-20 16:38:30 -0700741 {
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530742 vstatus = hdd_conf_hostarpoffload(pAdapter, FALSE);
743 if (!VOS_IS_STATUS_SUCCESS(vstatus))
744 {
745 hddLog(VOS_TRACE_LEVEL_INFO, "%s:Failed to disable ARPOFFLOAD "
746 "Feature %d\n", __func__, vstatus);
747 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700748 }
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530749 if (pHddCtx->dynamic_mcbc_filter.enableSuspend)
750 {
751 wlanResumeParam->configuredMcstBcstFilterSetting =
752 pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend;
753 }
754 else
755 {
756 wlanResumeParam->configuredMcstBcstFilterSetting =
757 pHddCtx->cfg_ini->mcastBcastFilterSetting;
758 }
759 sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam);
760 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700761 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700762
763#ifdef WLAN_FEATURE_PACKET_FILTERING
764 if (pHddCtx->cfg_ini->isMcAddrListFilter)
765 {
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530766 /*Multicast addr filtering is enabled*/
767 if (pAdapter->mc_addr_list.isFilterApplied)
Jeff Johnson295189b2012-06-20 16:38:30 -0700768 {
769 /*Filter applied during suspend mode*/
770 /*Clear it here*/
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530771 wlan_hdd_set_mc_addr_list(pAdapter, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700772 }
773 }
774#endif
775}
Jeff Johnson295189b2012-06-20 16:38:30 -0700776
Jeff Johnson295189b2012-06-20 16:38:30 -0700777//Suspend routine registered with Android OS
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800778void hdd_suspend_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -0700779{
780 hdd_context_t *pHddCtx = NULL;
781 v_CONTEXT_t pVosContext = NULL;
782
783 hdd_adapter_t *pAdapter = NULL;
784 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
785 VOS_STATUS status;
Jeff Johnsonbc676b42013-02-14 16:04:08 -0800786
Jeff Johnson295189b2012-06-20 16:38:30 -0700787 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__);
788
789 //Get the global VOSS context.
790 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
791 if(!pVosContext) {
792 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
793 return;
794 }
795
796 //Get the HDD context.
797 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
798
799 if(!pHddCtx) {
800 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
801 return;
802 }
803
804 if (pHddCtx->isLogpInProgress) {
805 hddLog(VOS_TRACE_LEVEL_ERROR,
806 "%s: Ignore suspend wlan, LOGP in progress!", __func__);
807 return;
808 }
809
Jeff Johnson295189b2012-06-20 16:38:30 -0700810 /*loop through all adapters. TBD fix for Concurrency */
811 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
812 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
813 {
814 pAdapter = pAdapterNode->pAdapter;
815 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -0700816 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -0700817 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
818
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -0700819 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -0700820 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
821 pAdapterNode = pNext;
822 continue;
823 }
824
825#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
826 if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
827 {
828 //stop the interface before putting the chip to standby
829 netif_tx_disable(pAdapter->dev);
830 netif_carrier_off(pAdapter->dev);
831 }
832 else if (pHddCtx->cfg_ini->nEnableSuspend ==
833 WLAN_MAP_SUSPEND_TO_DEEP_SLEEP)
834 {
835 //Execute deep sleep procedure
836 hdd_enter_deep_sleep(pHddCtx, pAdapter);
837 }
838#endif
839
Jeff Johnsone7245742012-09-05 17:12:55 -0700840 //Apply Dynamic Dtim For P2P
841 //Only if ignoreDynamicDtimInP2pMode is not set in ini
Jeff Johnson295189b2012-06-20 16:38:30 -0700842 if((pHddCtx->cfg_ini->enableDynamicDTIM ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700843 pHddCtx->cfg_ini->enableModulatedDTIM) &&
844 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
845 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
846 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
Jeff Johnson295189b2012-06-20 16:38:30 -0700847 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
848 (eConnectionState_Associated ==
849 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
850 (pHddCtx->cfg_ini->fIsBmpsEnabled))
851 {
852 tSirSetPowerParamsReq powerRequest = { 0 };
853
854 powerRequest.uIgnoreDTIM = 1;
855
856 /*Back up the actual values from CFG */
857 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM,
858 &pHddCtx->hdd_actual_ignore_DTIM_value);
859 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL,
860 &pHddCtx->hdd_actual_LI_value);
861
862 if(pHddCtx->cfg_ini->enableModulatedDTIM)
863 {
864 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
865 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
866 }
867 else
868 {
869 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
870 }
871
872 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
873 *specified during Enter/Exit BMPS when LCD off*/
874 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
875 NULL, eANI_BOOLEAN_FALSE);
876 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
877 NULL, eANI_BOOLEAN_FALSE);
878
879 /* switch to the DTIM specified in cfg.ini */
880 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
881 "Switch to DTIM%d \n", powerRequest.uListenInterval);
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -0800882 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700883
884 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
885 {
886 /* put the device into full power */
887 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
888
889 /* put the device back into BMPS */
890 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
891
892 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
893 }
894 }
895
Jeff Johnson295189b2012-06-20 16:38:30 -0700896 /*Suspend notification sent down to driver*/
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530897 hdd_conf_suspend_ind(pHddCtx, pAdapter);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +0530898
899#ifdef WLAN_FEATURE_GTK_OFFLOAD
900 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
901 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
902 {
903 eHalStatus ret;
904 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
905 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
906 (TRUE == pHddStaCtx->gtkOffloadRequestParams.requested))
907 {
908 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
909 &pHddStaCtx->gtkOffloadRequestParams.gtkOffloadReqParams,
910 pAdapter->sessionId);
911 if (eHAL_STATUS_SUCCESS != ret)
912 {
913 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
914 "%s: sme_SetGTKOffload failed, returned %d",
915 __func__, ret);
916 }
917 pHddStaCtx->gtkOffloadRequestParams.requested = FALSE;
918 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
919 "%s: sme_SetGTKOffload successfull",
920 __func__);
921 }
922 }
923#endif
924
Jeff Johnson295189b2012-06-20 16:38:30 -0700925 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
926 pAdapterNode = pNext;
927 }
928 pHddCtx->hdd_wlan_suspended = TRUE;
929
930#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
931 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
932 {
933 hdd_enter_standby(pHddCtx);
934 }
935#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700936
937 return;
938}
939
940static void hdd_PowerStateChangedCB
941(
942 v_PVOID_t callbackContext,
943 tPmcState newState
944)
945{
946 hdd_context_t *pHddCtx = callbackContext;
947
948 /* if the driver was not in BMPS during early suspend,
949 * the dynamic DTIM is now updated at Riva */
950 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended
951 && pHddCtx->cfg_ini->enableDynamicDTIM
952 && (pHddCtx->hdd_ignore_dtim_enabled == FALSE))
953 {
954 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
955 }
956 spin_lock(&pHddCtx->filter_lock);
Gopichand Nakkalac1b11522013-03-25 15:25:33 +0530957 if((newState == BMPS) && pHddCtx->hdd_wlan_suspended) {
Jeff Johnson295189b2012-06-20 16:38:30 -0700958 spin_unlock(&pHddCtx->filter_lock);
959 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700960 if(pHddCtx->hdd_mcastbcast_filter_set != TRUE)
961 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__);
962 }
963 else
964 spin_unlock(&pHddCtx->filter_lock);
965}
966
967
968
969void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx)
970{
971 v_CONTEXT_t pVosContext;
972 tHalHandle smeContext;
973
974 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
975 if (NULL == pVosContext)
976 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700977 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700978 return;
979 }
980 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
981 if (NULL == smeContext)
982 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700983 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700984 return;
985 }
986
987 spin_lock_init(&pHddCtx->filter_lock);
988 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
989 pHddCtx->cfg_ini->nEnableSuspend)
990 {
991 pmcRegisterDeviceStateUpdateInd(smeContext,
992 hdd_PowerStateChangedCB, pHddCtx);
993 }
994}
995
996void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx)
997{
998 v_CONTEXT_t pVosContext;
999 tHalHandle smeContext;
1000
1001 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1002 if (NULL == pVosContext)
1003 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001004 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001005 return;
1006 }
1007 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1008 if (NULL == smeContext)
1009 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001010 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001011 return;
1012 }
1013
1014 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1015 pHddCtx->cfg_ini->nEnableSuspend)
1016 {
1017 pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB);
1018 }
1019}
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301020#ifdef WLAN_FEATURE_GTK_OFFLOAD
1021void wlan_hdd_update_and_dissable_gtk_offload(hdd_adapter_t *pAdapter)
1022{
1023 eHalStatus ret;
1024 tpSirGtkOffloadParams pGtkOffloadReqParams;
1025 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1026
1027 pGtkOffloadReqParams =
1028 &pHddStaCtx->gtkOffloadRequestParams.gtkOffloadReqParams;
1029
1030 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1031 (0 != memcmp(&pGtkOffloadReqParams->bssId,
1032 &pHddStaCtx->conn_info.bssId, WNI_CFG_BSSID_LEN)) &&
1033 (FALSE == pHddStaCtx->gtkOffloadRequestParams.requested))
1034 {
1035 /* Host driver has previously offloaded GTK rekey */
1036 ret = sme_GetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1037 wlan_hdd_cfg80211_update_replayCounterCallback,
1038 pAdapter, pAdapter->sessionId);
1039 if (eHAL_STATUS_SUCCESS != ret)
1040 {
1041 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1042 "%s: sme_GetGTKOffload failed, returned %d",
1043 __func__, ret);
1044 }
1045 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1046 "%s: sme_GetGTKOffload successfull", __func__);
1047
1048 /* Sending GTK offload dissable */
1049 pGtkOffloadReqParams->ulFlags = GTK_OFFLOAD_DISABLE;
1050 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1051 pGtkOffloadReqParams, pAdapter->sessionId);
1052
1053 if (eHAL_STATUS_SUCCESS != ret)
1054 {
1055 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1056 "%s: failed to dissable GTK offload, returned %d",
1057 __func__, ret);
1058 }
1059 pHddStaCtx->gtkOffloadRequestParams.requested = FALSE;
1060 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1061 "%s: successfully dissabled GTK offload request to HAL",
1062 __func__);
1063 }
1064}
1065#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
Jeff Johnson295189b2012-06-20 16:38:30 -07001066
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001067void hdd_resume_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001068{
1069 hdd_context_t *pHddCtx = NULL;
1070 hdd_adapter_t *pAdapter = NULL;
1071 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1072 VOS_STATUS status;
1073 v_CONTEXT_t pVosContext = NULL;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001074
Jeff Johnson295189b2012-06-20 16:38:30 -07001075 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
1076
1077 //Get the global VOSS context.
1078 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1079 if(!pVosContext) {
1080 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1081 return;
1082 }
1083
1084 //Get the HDD context.
1085 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1086
1087 if(!pHddCtx) {
1088 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1089 return;
1090 }
1091
1092 if (pHddCtx->isLogpInProgress) {
1093 hddLog(VOS_TRACE_LEVEL_INFO,
1094 "%s: Ignore resume wlan, LOGP in progress!", __func__);
1095 return;
1096 }
1097
Jeff Johnson295189b2012-06-20 16:38:30 -07001098 pHddCtx->hdd_wlan_suspended = FALSE;
1099 /*loop through all adapters. Concurrency */
1100 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1101
1102 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1103 {
1104 pAdapter = pAdapterNode->pAdapter;
1105 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001106 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001107 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001108 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001109 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1110 pAdapterNode = pNext;
1111 continue;
1112 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301113
1114#ifdef WLAN_FEATURE_GTK_OFFLOAD
1115 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
1116 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
1117 {
1118 wlan_hdd_update_and_dissable_gtk_offload(pAdapter);
1119 }
1120#endif
1121
Jeff Johnson295189b2012-06-20 16:38:30 -07001122#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1123 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP)
1124 {
1125 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__);
1126 hdd_exit_deep_sleep(pAdapter);
1127 }
1128#endif
1129
1130 if(pHddCtx->hdd_ignore_dtim_enabled == TRUE)
1131 {
1132 /*Switch back to DTIM 1*/
1133 tSirSetPowerParamsReq powerRequest = { 0 };
1134
1135 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
1136 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
1137
1138 /*Disabled ModulatedDTIM if enabled on suspend*/
1139 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1140 powerRequest.uDTIMPeriod = 0;
1141
1142 /* Update ignoreDTIM and ListedInterval in CFG with default values */
1143 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1144 NULL, eANI_BOOLEAN_FALSE);
1145 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1146 NULL, eANI_BOOLEAN_FALSE);
1147
1148 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1149 "Switch to DTIM%d \n",powerRequest.uListenInterval);
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08001150 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001151
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301152 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
1153 {
1154 /* put the device into full power */
1155 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001156
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301157 /* put the device back into BMPS */
1158 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
Jeff Johnson295189b2012-06-20 16:38:30 -07001159
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301160 pHddCtx->hdd_ignore_dtim_enabled = FALSE;
1161 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001162 }
1163
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301164 hdd_conf_resume_ind(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001165 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1166 pAdapterNode = pNext;
1167 }
1168
1169#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1170 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY)
1171 {
1172 hdd_exit_standby(pHddCtx);
1173 }
1174#endif
1175
Jeff Johnson295189b2012-06-20 16:38:30 -07001176 return;
1177}
1178
Jeff Johnson295189b2012-06-20 16:38:30 -07001179VOS_STATUS hdd_wlan_reset_initialization(void)
1180{
Jeff Johnson295189b2012-06-20 16:38:30 -07001181 v_CONTEXT_t pVosContext = NULL;
1182
1183 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1184
1185 //Get the global VOSS context.
1186 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1187 if(!pVosContext)
1188 {
1189 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1190 return VOS_STATUS_E_FAILURE;
1191 }
1192
1193 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__);
1194
1195 // Prevent the phone from going to sleep
1196 hdd_prevent_suspend();
1197
Jeff Johnson295189b2012-06-20 16:38:30 -07001198 return VOS_STATUS_SUCCESS;
1199}
1200
1201
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001202/*
1203 * Based on the ioctl command recieved by HDD, put WLAN driver
1204 * into the quiet mode. This is the same as the early suspend
1205 * notification that driver used to listen
1206 */
1207void hdd_set_wlan_suspend_mode(bool suspend)
Jeff Johnson295189b2012-06-20 16:38:30 -07001208{
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001209 if (suspend)
1210 hdd_suspend_wlan();
1211 else
1212 hdd_resume_wlan();
Jeff Johnson295189b2012-06-20 16:38:30 -07001213}
1214
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001215static void hdd_ssr_timer_init(void)
1216{
1217 init_timer(&ssr_timer);
1218}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001219
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001220static void hdd_ssr_timer_del(void)
1221{
1222 del_timer(&ssr_timer);
1223 ssr_timer_started = false;
1224}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001225
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001226static void hdd_ssr_timer_cb(unsigned long data)
1227{
1228 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD SSR timer expired", __func__);
1229 VOS_BUG(0);
1230}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001231
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001232static void hdd_ssr_timer_start(int msec)
1233{
1234 if(ssr_timer_started)
1235 {
1236 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: trying to start SSR timer when it's running"
1237 ,__func__);
1238 }
1239 ssr_timer.expires = jiffies + msecs_to_jiffies(msec);
1240 ssr_timer.function = hdd_ssr_timer_cb;
1241 add_timer(&ssr_timer);
1242 ssr_timer_started = true;
1243}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001244
Jeff Johnson295189b2012-06-20 16:38:30 -07001245/* the HDD interface to WLAN driver shutdown,
1246 * the primary shutdown function in SSR
1247 */
1248VOS_STATUS hdd_wlan_shutdown(void)
1249{
1250 VOS_STATUS vosStatus;
1251 v_CONTEXT_t pVosContext = NULL;
1252 hdd_context_t *pHddCtx = NULL;
1253 pVosSchedContext vosSchedContext = NULL;
1254
1255 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__);
1256
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001257 /* if re-init never happens, then do SSR1 */
1258 hdd_ssr_timer_init();
1259 hdd_ssr_timer_start(HDD_SSR_BRING_UP_TIME);
1260
Jeff Johnson295189b2012-06-20 16:38:30 -07001261 /* Get the global VOSS context. */
1262 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1263 if(!pVosContext) {
1264 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1265 return VOS_STATUS_E_FAILURE;
1266 }
1267 /* Get the HDD context. */
1268 pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1269 if(!pHddCtx) {
1270 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1271 return VOS_STATUS_E_FAILURE;
1272 }
1273 hdd_reset_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001274 /* DeRegister with platform driver as client for Suspend/Resume */
1275 vosStatus = hddDeregisterPmOps(pHddCtx);
1276 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1277 {
1278 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
1279 }
1280
1281 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
1282 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1283 {
1284 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
1285 }
1286
1287 /* Disable IMPS/BMPS as we do not want the device to enter any power
1288 * save mode on its own during reset sequence
1289 */
1290 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1291 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1292 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1293
1294 vosSchedContext = get_vos_sched_ctxt();
1295
1296 /* Wakeup all driver threads */
1297 if(TRUE == pHddCtx->isMcThreadSuspended){
1298 complete(&vosSchedContext->ResumeMcEvent);
1299 pHddCtx->isMcThreadSuspended= FALSE;
1300 }
1301 if(TRUE == pHddCtx->isTxThreadSuspended){
1302 complete(&vosSchedContext->ResumeTxEvent);
1303 pHddCtx->isTxThreadSuspended= FALSE;
1304 }
1305 if(TRUE == pHddCtx->isRxThreadSuspended){
1306 complete(&vosSchedContext->ResumeRxEvent);
1307 pHddCtx->isRxThreadSuspended= FALSE;
1308 }
1309 /* Reset the Suspend Variable */
1310 pHddCtx->isWlanSuspended = FALSE;
1311
1312 /* Stop all the threads; we do not want any messages to be a processed,
1313 * any more and the best way to ensure that is to terminate the threads
1314 * gracefully.
1315 */
1316 /* Wait for MC to exit */
1317 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
1318 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
1319 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
1320 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
1321 wait_for_completion_interruptible(&vosSchedContext->McShutdown);
1322
1323 /* Wait for TX to exit */
1324 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
1325 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
1326 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
1327 wake_up_interruptible(&vosSchedContext->txWaitQueue);
1328 wait_for_completion_interruptible(&vosSchedContext->TxShutdown);
1329
1330 /* Wait for RX to exit */
1331 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
1332 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
1333 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
1334 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
1335 wait_for_completion_interruptible(&vosSchedContext->RxShutdown);
1336
1337#ifdef WLAN_BTAMP_FEATURE
1338 vosStatus = WLANBAP_Stop(pVosContext);
1339 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1340 {
1341 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1342 "%s: Failed to stop BAP",__func__);
1343 }
1344#endif //WLAN_BTAMP_FEATURE
1345 vosStatus = vos_wda_shutdown(pVosContext);
1346 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1347
1348 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
1349 /* Stop SME - Cannot invoke vos_stop as vos_stop relies
1350 * on threads being running to process the SYS Stop
1351 */
1352 vosStatus = sme_Stop(pHddCtx->hHal, TRUE);
1353 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1354
1355 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
1356 /* Stop MAC (PE and HAL) */
1357 vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
1358 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1359
1360 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
1361 /* Stop TL */
1362 vosStatus = WLANTL_Stop(pVosContext);
1363 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1364
Jeff Johnson295189b2012-06-20 16:38:30 -07001365 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001366 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__);
1367 /* Clean up message queues of TX and MC thread */
1368 vos_sched_flush_mc_mqs(vosSchedContext);
1369 vos_sched_flush_tx_mqs(vosSchedContext);
1370 vos_sched_flush_rx_mqs(vosSchedContext);
1371
1372 /* Deinit all the TX and MC queues */
1373 vos_sched_deinit_mqs(vosSchedContext);
1374 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__);
1375
1376 /* shutdown VOSS */
1377 vos_shutdown(pVosContext);
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05301378
1379 /*mac context has already been released in mac_close call
1380 so setting it to NULL in hdd context*/
1381 pHddCtx->hHal = (tHalHandle)NULL;
1382
Jeff Johnson295189b2012-06-20 16:38:30 -07001383 if (free_riva_power_on_lock("wlan"))
1384 {
1385 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
1386 __func__);
1387 }
1388 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete"
1389 ,__func__);
1390 return VOS_STATUS_SUCCESS;
1391}
1392
1393
1394
1395/* the HDD interface to WLAN driver re-init.
1396 * This is called to initialize/start WLAN driver after a shutdown.
1397 */
1398VOS_STATUS hdd_wlan_re_init(void)
1399{
1400 VOS_STATUS vosStatus;
1401 v_CONTEXT_t pVosContext = NULL;
1402 hdd_context_t *pHddCtx = NULL;
1403 eHalStatus halStatus;
1404#ifdef WLAN_BTAMP_FEATURE
1405 hdd_config_t *pConfig = NULL;
1406 WLANBAP_ConfigType btAmpConfig;
1407#endif
1408
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001409 hdd_ssr_timer_del();
Jeff Johnson295189b2012-06-20 16:38:30 -07001410 hdd_prevent_suspend();
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001411
1412 /* The driver should always be initialized in STA mode after SSR */
1413 hdd_set_conparam(0);
1414
Jeff Johnson295189b2012-06-20 16:38:30 -07001415 /* Re-open VOSS, it is a re-open b'se control transport was never closed. */
1416 vosStatus = vos_open(&pVosContext, 0);
1417 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1418 {
1419 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
1420 goto err_re_init;
1421 }
1422
1423 /* Get the HDD context. */
1424 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1425 if(!pHddCtx)
1426 {
1427 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1428 goto err_vosclose;
1429 }
1430
1431 /* Save the hal context in Adapter */
1432 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
1433 if ( NULL == pHddCtx->hHal )
1434 {
1435 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
1436 goto err_vosclose;
1437 }
1438
1439 /* Set the SME configuration parameters. */
1440 vosStatus = hdd_set_sme_config(pHddCtx);
1441 if ( VOS_STATUS_SUCCESS != vosStatus )
1442 {
1443 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
1444 goto err_vosclose;
1445 }
1446
1447 /* Initialize the WMM module */
1448 vosStatus = hdd_wmm_init(pHddCtx);
1449 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
1450 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001451 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001452 goto err_vosclose;
1453 }
1454
1455 vosStatus = vos_preStart( pHddCtx->pvosContext );
1456 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1457 {
1458 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
1459 goto err_vosclose;
1460 }
1461
1462 /* In the integrated architecture we update the configuration from
1463 the INI file and from NV before vOSS has been started so that
1464 the final contents are available to send down to the cCPU */
1465 /* Apply the cfg.ini to cfg.dat */
1466 if (FALSE == hdd_update_config_dat(pHddCtx))
1467 {
1468 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
1469 goto err_vosclose;
1470 }
1471
1472 /* Set the MAC Address, currently this is used by HAL to add self sta.
1473 * Remove this once self sta is added as part of session open. */
1474 halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID,
1475 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
1476 sizeof(pHddCtx->cfg_ini->intfMacAddr[0]));
1477 if (!HAL_STATUS_SUCCESS(halStatus))
1478 {
1479 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
1480 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus);
1481 goto err_vosclose;
1482 }
1483
1484 /* Start VOSS which starts up the SME/MAC/HAL modules and everything else
1485 Note: Firmware image will be read and downloaded inside vos_start API */
1486 vosStatus = vos_start( pVosContext );
1487 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1488 {
1489 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
1490 goto err_vosclose;
1491 }
1492
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07001493 /* Exchange capability info between Host and FW and also get versioning info from FW */
1494 hdd_exchange_version_and_caps(pHddCtx);
1495
Jeff Johnson295189b2012-06-20 16:38:30 -07001496 vosStatus = hdd_post_voss_start_config( pHddCtx );
1497 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1498 {
1499 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
1500 __func__);
1501 goto err_vosstop;
1502 }
1503
1504#ifdef WLAN_BTAMP_FEATURE
1505 vosStatus = WLANBAP_Open(pVosContext);
1506 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1507 {
1508 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1509 "%s: Failed to open BAP",__func__);
1510 goto err_vosstop;
1511 }
1512 vosStatus = BSL_Init(pVosContext);
1513 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1514 {
1515 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1516 "%s: Failed to Init BSL",__func__);
1517 goto err_bap_close;
1518 }
1519 vosStatus = WLANBAP_Start(pVosContext);
1520 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1521 {
1522 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1523 "%s: Failed to start TL",__func__);
1524 goto err_bap_close;
1525 }
1526 pConfig = pHddCtx->cfg_ini;
1527 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
1528 vosStatus = WLANBAP_SetConfig(&btAmpConfig);
1529#endif //WLAN_BTAMP_FEATURE
1530
1531 /* Restart all adapters */
1532 hdd_start_all_adapters(pHddCtx);
1533 pHddCtx->isLogpInProgress = FALSE;
1534 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001535 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001536
1537 /* Register with platform driver as client for Suspend/Resume */
1538 vosStatus = hddRegisterPmOps(pHddCtx);
1539 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1540 {
1541 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
1542 goto err_bap_stop;
1543 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001544 /* Allow the phone to go to sleep */
1545 hdd_allow_suspend();
1546 /* register for riva power on lock */
1547 if (req_riva_power_on_lock("wlan"))
1548 {
1549 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
1550 __func__);
1551 goto err_unregister_pmops;
1552 }
1553 goto success;
1554
1555err_unregister_pmops:
1556 hddDeregisterPmOps(pHddCtx);
1557
1558err_bap_stop:
Jeff Johnson32d95a32012-09-10 13:15:23 -07001559#ifdef CONFIG_HAS_EARLYSUSPEND
1560 hdd_unregister_mcast_bcast_filter(pHddCtx);
1561#endif
1562 hdd_close_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001563#ifdef WLAN_BTAMP_FEATURE
Jeff Johnson32d95a32012-09-10 13:15:23 -07001564 WLANBAP_Stop(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07001565#endif
1566
1567#ifdef WLAN_BTAMP_FEATURE
1568err_bap_close:
1569 WLANBAP_Close(pVosContext);
1570#endif
1571
1572err_vosstop:
1573 vos_stop(pVosContext);
1574
1575err_vosclose:
1576 vos_close(pVosContext);
1577 vos_sched_close(pVosContext);
1578 if (pHddCtx)
1579 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001580 /* Unregister the Net Device Notifier */
1581 unregister_netdevice_notifier(&hdd_netdev_notifier);
1582 /* Clean up HDD Nlink Service */
1583 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1584 nl_srv_exit();
Jeff Johnson295189b2012-06-20 16:38:30 -07001585 /* Free up dynamically allocated members inside HDD Adapter */
1586 kfree(pHddCtx->cfg_ini);
1587 pHddCtx->cfg_ini= NULL;
1588
Jeff Johnson295189b2012-06-20 16:38:30 -07001589 wiphy_unregister(pHddCtx->wiphy);
1590 wiphy_free(pHddCtx->wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07001591 }
1592 vos_preClose(&pVosContext);
1593
1594#ifdef MEMORY_DEBUG
1595 vos_mem_exit();
1596#endif
1597
1598err_re_init:
1599 /* Allow the phone to go to sleep */
1600 hdd_allow_suspend();
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001601 return -EPERM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001602
1603success:
1604 /* Trigger replay of BTC events */
1605 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1606 return VOS_STATUS_SUCCESS;
1607}