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