blob: a71171826aee2c79e2a6912a9c74f181207f7793 [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
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530449/*
450 * Function: hdd_conf_hostoffload
451 * Central function to configure the supported offloads,
452 * either enable or disable them.
453 */
454void hdd_conf_hostoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
455{
456 hdd_context_t *pHddCtx = NULL;
457 v_CONTEXT_t *pVosContext = NULL;
458 VOS_STATUS vstatus = VOS_STATUS_E_FAILURE;
459
460 hddLog(VOS_TRACE_LEVEL_INFO, FL("Configuring offloads with flag: %d"),
461 fenable);
462
463 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
464
465 if (NULL == pVosContext)
466 {
467 hddLog(VOS_TRACE_LEVEL_ERROR, FL(" Global VOS context is Null"));
468 return;
469 }
470
471 //Get the HDD context.
472 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
473
474 if (NULL == pHddCtx)
475 {
476 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: HDD context is Null", __func__);
477 return;
478 }
479
480 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
481 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
482 {
483 if (fenable)
484 {
485 if (eConnectionState_Associated ==
486 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)
487 {
488 if ((pHddCtx->cfg_ini->fhostArpOffload))
489 {
490 /*
491 * Configure the ARP Offload.
492 * Even if it fails we have to reconfigure the MC/BC
493 * filter flag as we want RIVA not to drop BroadCast
494 * Packets
495 */
496 hddLog(VOS_TRACE_LEVEL_INFO,
497 FL("Calling ARP Offload with flag: %d"), fenable);
498 vstatus = hdd_conf_arp_offload(pAdapter, fenable);
499 pHddCtx->configuredMcastBcastFilter &=
500 ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST);
501
502 if (!VOS_IS_STATUS_SUCCESS(vstatus))
503 {
504 hddLog(VOS_TRACE_LEVEL_ERROR,
505 "Failed to enable ARPOFfloadFeature %d",
506 vstatus);
507 }
508 }
509 //Configure GTK_OFFLOAD
510#ifdef WLAN_FEATURE_GTK_OFFLOAD
511 hdd_conf_gtk_offload(pAdapter, fenable);
512#endif
513 }
514 }
515 else
516 {
517 //Disable ARPOFFLOAD
518 if (pHddCtx->cfg_ini->fhostArpOffload)
519 {
520 vstatus = hdd_conf_arp_offload(pAdapter, fenable);
521 if (!VOS_IS_STATUS_SUCCESS(vstatus))
522 {
523 hddLog(VOS_TRACE_LEVEL_ERROR,
524 "Failed to disable ARPOFfloadFeature %d", vstatus);
525 }
526 }
527 //Disable GTK_OFFLOAD
528#ifdef WLAN_FEATURE_GTK_OFFLOAD
529 hdd_conf_gtk_offload(pAdapter, fenable);
530#endif
531 }
532 }
533 return;
534}
535
536VOS_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
Jeff Johnson295189b2012-06-20 16:38:30 -0700537{
538 struct in_ifaddr **ifap = NULL;
539 struct in_ifaddr *ifa = NULL;
540 struct in_device *in_dev;
541 int i = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700542 tSirHostOffloadReq offLoadRequest;
Yathish9f22e662012-12-10 14:21:35 -0800543 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700544
545 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700546
Jeff Johnson295189b2012-06-20 16:38:30 -0700547 if(fenable)
548 {
549 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
550 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530551 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700552 ifap = &ifa->ifa_next)
553 {
554 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
555 {
556 break; /* found */
557 }
558 }
559 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700560 if(ifa && ifa->ifa_local)
561 {
562 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
563 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
564
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530565 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Enabled \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700566
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530567 if((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
568 pHddCtx->configuredMcastBcastFilter) ||
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700569 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530570 pHddCtx->configuredMcastBcastFilter))
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700571 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530572 offLoadRequest.enableOrDisable =
573 SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700574 }
575
576 //converting u32 to IPV4 address
577 for(i = 0 ; i < 4; i++)
578 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530579 offLoadRequest.params.hostIpv4Addr[i] =
Jeff Johnson295189b2012-06-20 16:38:30 -0700580 (ifa->ifa_local >> (i*8) ) & 0xFF ;
581 }
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530582 hddLog(VOS_TRACE_LEVEL_INFO, " Enable SME HostOffload: %d.%d.%d.%d",
Jeff Johnson295189b2012-06-20 16:38:30 -0700583 offLoadRequest.params.hostIpv4Addr[0],
584 offLoadRequest.params.hostIpv4Addr[1],
585 offLoadRequest.params.hostIpv4Addr[2],
586 offLoadRequest.params.hostIpv4Addr[3]);
587
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530588 if (eHAL_STATUS_SUCCESS !=
589 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
590 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700591 {
592 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to enable HostOffload "
593 "feature\n", __func__);
594 return VOS_STATUS_E_FAILURE;
595 }
596 return VOS_STATUS_SUCCESS;
597 }
598 else
599 {
600 hddLog(VOS_TRACE_LEVEL_INFO, "%s:IP Address is not assigned \n", __func__);
601 return VOS_STATUS_E_AGAIN;
602 }
603 }
604 else
605 {
606 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
607 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
608 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
609
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530610 if (eHAL_STATUS_SUCCESS !=
611 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
612 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700613 {
614 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to disable host "
615 "offload feature\n", __func__);
616 return VOS_STATUS_E_FAILURE;
617 }
618 return VOS_STATUS_SUCCESS;
619 }
620}
621
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530622/*
623 * This function is called before setting mcbc filters
624 * to modify filter value considering ARP
625*/
626void hdd_mcbc_filter_modification(hdd_context_t* pHddCtx, v_BOOL_t arpFlag,
627 tANI_U8 *pMcBcFilter)
628{
629 if (TRUE == arpFlag)
630 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530631 /* ARP offload is enabled, do not block bcast packets at RXP
632 * Will be using Bitmasking to reset the filter. As we have
633 * disable Broadcast filtering, Anding with the negation
634 * of Broadcast BIT
635 */
636 *pMcBcFilter = pHddCtx->configuredMcastBcastFilter &
637 ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST);
638 pHddCtx->configuredMcastBcastFilter = *pMcBcFilter;
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530639 }
640 else
641 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530642 *pMcBcFilter = pHddCtx->configuredMcastBcastFilter;
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530643 }
644}
645
Jeff Johnson295189b2012-06-20 16:38:30 -0700646void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter)
647{
648 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700649 tpSirWlanSetRxpFilters wlanRxpFilterParam =
650 vos_mem_malloc(sizeof(tSirWlanSetRxpFilters));
651 if(NULL == wlanRxpFilterParam)
652 {
653 hddLog(VOS_TRACE_LEVEL_FATAL,
654 "%s: vos_mem_alloc failed ", __func__);
655 return;
656 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700657 hddLog(VOS_TRACE_LEVEL_INFO,
658 "%s: Configuring Mcast/Bcast Filter Setting. setfilter %d", __func__, setfilter);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530659 if (TRUE == setfilter)
660 {
661 if (pHddCtx->cfg_ini->fhostArpOffload)
662 {
663 hdd_mcbc_filter_modification(pHddCtx, TRUE,
664 &wlanRxpFilterParam->configuredMcstBcstFilterSetting);
665 }
666 else
667 {
668 hdd_mcbc_filter_modification(pHddCtx, FALSE,
669 &wlanRxpFilterParam->configuredMcstBcstFilterSetting);
670 }
671 }
672 else
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530673 {
674 /*Use the current configured value to clear*/
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530675 wlanRxpFilterParam->configuredMcstBcstFilterSetting =
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530676 pHddCtx->configuredMcastBcastFilter;
677 }
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530678
Jeff Johnson295189b2012-06-20 16:38:30 -0700679 wlanRxpFilterParam->setMcstBcstFilter = setfilter;
Jeff Johnson295189b2012-06-20 16:38:30 -0700680 halStatus = sme_ConfigureRxpFilter(pHddCtx->hHal, wlanRxpFilterParam);
Chilam Ngc4244af2013-04-01 15:37:32 -0700681 if (eHAL_STATUS_SUCCESS != halStatus)
682 vos_mem_free(wlanRxpFilterParam);
Jeff Johnson295189b2012-06-20 16:38:30 -0700683 if(setfilter && (eHAL_STATUS_SUCCESS == halStatus))
684 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
685}
686
Jeff Johnson295189b2012-06-20 16:38:30 -0700687static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx,
688 hdd_adapter_t *pAdapter)
689{
690 eHalStatus halStatus = eHAL_STATUS_FAILURE;
691 tpSirWlanSuspendParam wlanSuspendParam =
692 vos_mem_malloc(sizeof(tSirWlanSuspendParam));
693
694 if(NULL == wlanSuspendParam)
695 {
696 hddLog(VOS_TRACE_LEVEL_FATAL,
697 "%s: vos_mem_alloc failed ", __func__);
698 return;
699 }
700
701 hddLog(VOS_TRACE_LEVEL_INFO,
702 "%s: send wlan suspend indication", __func__);
703
704 if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER))
705 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530706 //Configure supported OffLoads
707 hdd_conf_hostoffload(pAdapter, TRUE);
708 wlanSuspendParam->configuredMcstBcstFilterSetting = pHddCtx->configuredMcastBcastFilter;
Jeff Johnson295189b2012-06-20 16:38:30 -0700709
710#ifdef WLAN_FEATURE_PACKET_FILTERING
711 if (pHddCtx->cfg_ini->isMcAddrListFilter)
712 {
713 /*Multicast addr list filter is enabled during suspend*/
714 if (((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
715 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT))
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530716 && pAdapter->mc_addr_list.mc_cnt
Jeff Johnson295189b2012-06-20 16:38:30 -0700717 && (eConnectionState_Associated ==
718 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
719 {
720 /*set the filter*/
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530721 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700722 }
723 }
724#endif
725 }
726
727 halStatus = sme_ConfigureSuspendInd(pHddCtx->hHal, wlanSuspendParam);
728 if(eHAL_STATUS_SUCCESS == halStatus)
729 {
730 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
Chilam Ngc4244af2013-04-01 15:37:32 -0700731 } else {
732 vos_mem_free(wlanSuspendParam);
Jeff Johnson295189b2012-06-20 16:38:30 -0700733 }
734}
735
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530736static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700737{
Chilam Ngc4244af2013-04-01 15:37:32 -0700738 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Yathish9f22e662012-12-10 14:21:35 -0800739 hdd_context_t* pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Chilam Ngc4244af2013-04-01 15:37:32 -0700740 tpSirWlanResumeParam wlanResumeParam;
Jeff Johnson295189b2012-06-20 16:38:30 -0700741
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530742 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700743 "%s: send wlan resume indication", __func__);
744
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530745 if (pHddCtx->hdd_mcastbcast_filter_set == TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -0700746 {
Chilam Ngc4244af2013-04-01 15:37:32 -0700747 wlanResumeParam = vos_mem_malloc(sizeof(tSirWlanResumeParam));
748
749 if(NULL == wlanResumeParam)
750 {
751 hddLog(VOS_TRACE_LEVEL_FATAL,
752 "%s: vos_mem_alloc failed ", __func__);
753 return;
754 }
755
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530756 //Disable supported OffLoads
757 hdd_conf_hostoffload(pAdapter, FALSE);
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530758
759 wlanResumeParam->configuredMcstBcstFilterSetting =
760 pHddCtx->configuredMcastBcastFilter;
Chilam Ngc4244af2013-04-01 15:37:32 -0700761 halStatus = sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam);
762 if (eHAL_STATUS_SUCCESS != halStatus)
763 vos_mem_free(wlanResumeParam);
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530764 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700765 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700766
Chilam Ngc4244af2013-04-01 15:37:32 -0700767
Jeff Johnson295189b2012-06-20 16:38:30 -0700768#ifdef WLAN_FEATURE_PACKET_FILTERING
769 if (pHddCtx->cfg_ini->isMcAddrListFilter)
770 {
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530771 /*Multicast addr filtering is enabled*/
772 if (pAdapter->mc_addr_list.isFilterApplied)
Jeff Johnson295189b2012-06-20 16:38:30 -0700773 {
774 /*Filter applied during suspend mode*/
775 /*Clear it here*/
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530776 wlan_hdd_set_mc_addr_list(pAdapter, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700777 }
778 }
779#endif
780}
Jeff Johnson295189b2012-06-20 16:38:30 -0700781
Jeff Johnson295189b2012-06-20 16:38:30 -0700782//Suspend routine registered with Android OS
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800783void hdd_suspend_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -0700784{
785 hdd_context_t *pHddCtx = NULL;
786 v_CONTEXT_t pVosContext = NULL;
787
Jeff Johnson295189b2012-06-20 16:38:30 -0700788 VOS_STATUS status;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +0530789 hdd_adapter_t *pAdapter = NULL;
790 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Jeff Johnsonbc676b42013-02-14 16:04:08 -0800791
Jeff Johnson295189b2012-06-20 16:38:30 -0700792 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__);
793
794 //Get the global VOSS context.
795 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
796 if(!pVosContext) {
797 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
798 return;
799 }
800
801 //Get the HDD context.
802 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
803
804 if(!pHddCtx) {
805 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
806 return;
807 }
808
809 if (pHddCtx->isLogpInProgress) {
810 hddLog(VOS_TRACE_LEVEL_ERROR,
811 "%s: Ignore suspend wlan, LOGP in progress!", __func__);
812 return;
813 }
814
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +0530815 hdd_set_pwrparams(pHddCtx);
816
817 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
818 {
819 /* put the device into full power */
820 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
821
822 /* put the device back into BMPS */
823 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
824
825 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
826 }
827
Jeff Johnson295189b2012-06-20 16:38:30 -0700828 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
829 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
830 {
831 pAdapter = pAdapterNode->pAdapter;
832 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -0700833 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -0700834 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
835
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -0700836 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -0700837 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
838 pAdapterNode = pNext;
839 continue;
840 }
841
842#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
843 if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
844 {
845 //stop the interface before putting the chip to standby
846 netif_tx_disable(pAdapter->dev);
847 netif_carrier_off(pAdapter->dev);
848 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +0530849 else if (pHddCtx->cfg_ini->nEnableSuspend ==
Jeff Johnson295189b2012-06-20 16:38:30 -0700850 WLAN_MAP_SUSPEND_TO_DEEP_SLEEP)
851 {
852 //Execute deep sleep procedure
853 hdd_enter_deep_sleep(pHddCtx, pAdapter);
854 }
855#endif
Gopichand Nakkalad36ee622013-05-07 14:13:27 +0530856
857 /*Suspend notification sent down to driver*/
858 hdd_conf_suspend_ind(pHddCtx, pAdapter);
859
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +0530860 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
861 pAdapterNode = pNext;
862 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +0530863 pHddCtx->hdd_wlan_suspended = TRUE;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +0530864
Jeff Johnson295189b2012-06-20 16:38:30 -0700865#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
866 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
867 {
868 hdd_enter_standby(pHddCtx);
869 }
870#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700871
872 return;
873}
874
875static void hdd_PowerStateChangedCB
876(
877 v_PVOID_t callbackContext,
878 tPmcState newState
879)
880{
881 hdd_context_t *pHddCtx = callbackContext;
882
883 /* if the driver was not in BMPS during early suspend,
884 * the dynamic DTIM is now updated at Riva */
885 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended
886 && pHddCtx->cfg_ini->enableDynamicDTIM
887 && (pHddCtx->hdd_ignore_dtim_enabled == FALSE))
888 {
889 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
890 }
891 spin_lock(&pHddCtx->filter_lock);
Gopichand Nakkalac1b11522013-03-25 15:25:33 +0530892 if((newState == BMPS) && pHddCtx->hdd_wlan_suspended) {
Jeff Johnson295189b2012-06-20 16:38:30 -0700893 spin_unlock(&pHddCtx->filter_lock);
894 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700895 if(pHddCtx->hdd_mcastbcast_filter_set != TRUE)
896 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__);
897 }
898 else
899 spin_unlock(&pHddCtx->filter_lock);
900}
901
902
903
904void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx)
905{
906 v_CONTEXT_t pVosContext;
907 tHalHandle smeContext;
908
909 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
910 if (NULL == pVosContext)
911 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700912 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700913 return;
914 }
915 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
916 if (NULL == smeContext)
917 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700918 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700919 return;
920 }
921
922 spin_lock_init(&pHddCtx->filter_lock);
923 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
924 pHddCtx->cfg_ini->nEnableSuspend)
925 {
926 pmcRegisterDeviceStateUpdateInd(smeContext,
927 hdd_PowerStateChangedCB, pHddCtx);
928 }
929}
930
931void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx)
932{
933 v_CONTEXT_t pVosContext;
934 tHalHandle smeContext;
935
936 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
937 if (NULL == pVosContext)
938 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700939 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700940 return;
941 }
942 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
943 if (NULL == smeContext)
944 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700945 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700946 return;
947 }
948
949 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
950 pHddCtx->cfg_ini->nEnableSuspend)
951 {
952 pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB);
953 }
954}
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530955
Gopichand Nakkala870cbae2013-03-15 21:16:09 +0530956#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530957void hdd_conf_gtk_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +0530958{
959 eHalStatus ret;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +0530960 tSirGtkOffloadParams hddGtkOffloadReqParams;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +0530961 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
962
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530963 if(fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +0530964 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530965 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
966 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags ))
967 {
968 vos_mem_copy(&hddGtkOffloadReqParams,
969 &pHddStaCtx->gtkOffloadReqParams,
970 sizeof (tSirGtkOffloadParams));
Gopichand Nakkalad36ee622013-05-07 14:13:27 +0530971
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530972 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
973 &hddGtkOffloadReqParams, pAdapter->sessionId);
974 if (eHAL_STATUS_SUCCESS != ret)
975 {
976 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
977 "%s: sme_SetGTKOffload failed, returned %d",
978 __func__, ret);
979 return;
980 }
981
982 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
983 "%s: sme_SetGTKOffload successfull", __func__);
984 }
985
986 }
987 else
988 {
989 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
990 (0 == memcmp(&pHddStaCtx->gtkOffloadReqParams.bssId,
991 &pHddStaCtx->conn_info.bssId, WNI_CFG_BSSID_LEN)) &&
992 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags))
993 {
994
995 /* Host driver has previously offloaded GTK rekey */
996 ret = sme_GetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala870cbae2013-03-15 21:16:09 +0530997 wlan_hdd_cfg80211_update_replayCounterCallback,
998 pAdapter, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530999 if (eHAL_STATUS_SUCCESS != ret)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301000
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301001 {
1002 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1003 "%s: sme_GetGTKOffload failed, returned %d",
1004 __func__, ret);
1005 return;
1006 }
1007 else
1008 {
1009 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1010 "%s: sme_GetGTKOffload successful",
1011 __func__);
1012
1013 /* Sending GTK offload dissable */
1014 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
1015 sizeof (tSirGtkOffloadParams));
1016 hddGtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE;
1017 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301018 &hddGtkOffloadReqParams, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301019 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 return;
1025 }
1026 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1027 "%s: successfully dissabled GTK offload request to HAL",
1028 __func__);
1029 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301030 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301031 }
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301032 return;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301033}
1034#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
Jeff Johnson295189b2012-06-20 16:38:30 -07001035
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001036void hdd_resume_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001037{
1038 hdd_context_t *pHddCtx = NULL;
1039 hdd_adapter_t *pAdapter = NULL;
1040 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1041 VOS_STATUS status;
1042 v_CONTEXT_t pVosContext = NULL;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001043
Jeff Johnson295189b2012-06-20 16:38:30 -07001044 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
1045
1046 //Get the global VOSS context.
1047 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1048 if(!pVosContext) {
1049 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1050 return;
1051 }
1052
1053 //Get the HDD context.
1054 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1055
1056 if(!pHddCtx) {
1057 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1058 return;
1059 }
1060
1061 if (pHddCtx->isLogpInProgress) {
1062 hddLog(VOS_TRACE_LEVEL_INFO,
1063 "%s: Ignore resume wlan, LOGP in progress!", __func__);
1064 return;
1065 }
1066
Jeff Johnson295189b2012-06-20 16:38:30 -07001067 pHddCtx->hdd_wlan_suspended = FALSE;
1068 /*loop through all adapters. Concurrency */
1069 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1070
1071 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1072 {
1073 pAdapter = pAdapterNode->pAdapter;
1074 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001075 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001076 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001077 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001078 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1079 pAdapterNode = pNext;
1080 continue;
1081 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301082
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301083
Jeff Johnson295189b2012-06-20 16:38:30 -07001084#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1085 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP)
1086 {
1087 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__);
1088 hdd_exit_deep_sleep(pAdapter);
1089 }
1090#endif
1091
1092 if(pHddCtx->hdd_ignore_dtim_enabled == TRUE)
1093 {
1094 /*Switch back to DTIM 1*/
1095 tSirSetPowerParamsReq powerRequest = { 0 };
1096
1097 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
1098 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07001099 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001100
1101 /*Disabled ModulatedDTIM if enabled on suspend*/
1102 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1103 powerRequest.uDTIMPeriod = 0;
1104
1105 /* Update ignoreDTIM and ListedInterval in CFG with default values */
1106 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1107 NULL, eANI_BOOLEAN_FALSE);
1108 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1109 NULL, eANI_BOOLEAN_FALSE);
1110
1111 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1112 "Switch to DTIM%d \n",powerRequest.uListenInterval);
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08001113 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001114
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301115 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
1116 {
1117 /* put the device into full power */
1118 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001119
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301120 /* put the device back into BMPS */
1121 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
Jeff Johnson295189b2012-06-20 16:38:30 -07001122
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301123 pHddCtx->hdd_ignore_dtim_enabled = FALSE;
1124 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001125 }
1126
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301127 hdd_conf_resume_ind(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001128 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1129 pAdapterNode = pNext;
1130 }
1131
1132#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1133 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY)
1134 {
1135 hdd_exit_standby(pHddCtx);
1136 }
1137#endif
1138
Jeff Johnson295189b2012-06-20 16:38:30 -07001139 return;
1140}
1141
Jeff Johnson295189b2012-06-20 16:38:30 -07001142VOS_STATUS hdd_wlan_reset_initialization(void)
1143{
Jeff Johnson295189b2012-06-20 16:38:30 -07001144 v_CONTEXT_t pVosContext = NULL;
1145
1146 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1147
1148 //Get the global VOSS context.
1149 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1150 if(!pVosContext)
1151 {
1152 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1153 return VOS_STATUS_E_FAILURE;
1154 }
1155
1156 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__);
1157
1158 // Prevent the phone from going to sleep
1159 hdd_prevent_suspend();
1160
Jeff Johnson295189b2012-06-20 16:38:30 -07001161 return VOS_STATUS_SUCCESS;
1162}
1163
1164
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001165/*
1166 * Based on the ioctl command recieved by HDD, put WLAN driver
1167 * into the quiet mode. This is the same as the early suspend
1168 * notification that driver used to listen
1169 */
1170void hdd_set_wlan_suspend_mode(bool suspend)
Jeff Johnson295189b2012-06-20 16:38:30 -07001171{
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001172 if (suspend)
1173 hdd_suspend_wlan();
1174 else
1175 hdd_resume_wlan();
Jeff Johnson295189b2012-06-20 16:38:30 -07001176}
1177
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001178static void hdd_ssr_timer_init(void)
1179{
1180 init_timer(&ssr_timer);
1181}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001182
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001183static void hdd_ssr_timer_del(void)
1184{
1185 del_timer(&ssr_timer);
1186 ssr_timer_started = false;
1187}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001188
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001189static void hdd_ssr_timer_cb(unsigned long data)
1190{
1191 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD SSR timer expired", __func__);
1192 VOS_BUG(0);
1193}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001194
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001195static void hdd_ssr_timer_start(int msec)
1196{
1197 if(ssr_timer_started)
1198 {
1199 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: trying to start SSR timer when it's running"
1200 ,__func__);
1201 }
1202 ssr_timer.expires = jiffies + msecs_to_jiffies(msec);
1203 ssr_timer.function = hdd_ssr_timer_cb;
1204 add_timer(&ssr_timer);
1205 ssr_timer_started = true;
1206}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001207
Jeff Johnson295189b2012-06-20 16:38:30 -07001208/* the HDD interface to WLAN driver shutdown,
1209 * the primary shutdown function in SSR
1210 */
1211VOS_STATUS hdd_wlan_shutdown(void)
1212{
1213 VOS_STATUS vosStatus;
1214 v_CONTEXT_t pVosContext = NULL;
1215 hdd_context_t *pHddCtx = NULL;
1216 pVosSchedContext vosSchedContext = NULL;
1217
1218 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__);
1219
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001220 /* if re-init never happens, then do SSR1 */
1221 hdd_ssr_timer_init();
1222 hdd_ssr_timer_start(HDD_SSR_BRING_UP_TIME);
1223
Jeff Johnson295189b2012-06-20 16:38:30 -07001224 /* Get the global VOSS context. */
1225 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1226 if(!pVosContext) {
1227 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1228 return VOS_STATUS_E_FAILURE;
1229 }
1230 /* Get the HDD context. */
1231 pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1232 if(!pHddCtx) {
1233 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1234 return VOS_STATUS_E_FAILURE;
1235 }
1236 hdd_reset_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001237 /* DeRegister with platform driver as client for Suspend/Resume */
1238 vosStatus = hddDeregisterPmOps(pHddCtx);
1239 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1240 {
1241 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
1242 }
1243
1244 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
1245 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1246 {
1247 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
1248 }
1249
1250 /* Disable IMPS/BMPS as we do not want the device to enter any power
1251 * save mode on its own during reset sequence
1252 */
1253 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1254 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1255 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1256
1257 vosSchedContext = get_vos_sched_ctxt();
1258
1259 /* Wakeup all driver threads */
1260 if(TRUE == pHddCtx->isMcThreadSuspended){
1261 complete(&vosSchedContext->ResumeMcEvent);
1262 pHddCtx->isMcThreadSuspended= FALSE;
1263 }
1264 if(TRUE == pHddCtx->isTxThreadSuspended){
1265 complete(&vosSchedContext->ResumeTxEvent);
1266 pHddCtx->isTxThreadSuspended= FALSE;
1267 }
1268 if(TRUE == pHddCtx->isRxThreadSuspended){
1269 complete(&vosSchedContext->ResumeRxEvent);
1270 pHddCtx->isRxThreadSuspended= FALSE;
1271 }
1272 /* Reset the Suspend Variable */
1273 pHddCtx->isWlanSuspended = FALSE;
1274
1275 /* Stop all the threads; we do not want any messages to be a processed,
1276 * any more and the best way to ensure that is to terminate the threads
1277 * gracefully.
1278 */
1279 /* Wait for MC to exit */
1280 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
1281 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
1282 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
1283 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
1284 wait_for_completion_interruptible(&vosSchedContext->McShutdown);
1285
1286 /* Wait for TX to exit */
1287 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
1288 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
1289 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
1290 wake_up_interruptible(&vosSchedContext->txWaitQueue);
1291 wait_for_completion_interruptible(&vosSchedContext->TxShutdown);
1292
1293 /* Wait for RX to exit */
1294 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
1295 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
1296 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
1297 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
1298 wait_for_completion_interruptible(&vosSchedContext->RxShutdown);
1299
1300#ifdef WLAN_BTAMP_FEATURE
1301 vosStatus = WLANBAP_Stop(pVosContext);
1302 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1303 {
1304 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1305 "%s: Failed to stop BAP",__func__);
1306 }
1307#endif //WLAN_BTAMP_FEATURE
1308 vosStatus = vos_wda_shutdown(pVosContext);
1309 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1310
1311 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
1312 /* Stop SME - Cannot invoke vos_stop as vos_stop relies
1313 * on threads being running to process the SYS Stop
1314 */
1315 vosStatus = sme_Stop(pHddCtx->hHal, TRUE);
1316 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1317
1318 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
1319 /* Stop MAC (PE and HAL) */
1320 vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
1321 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1322
1323 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
1324 /* Stop TL */
1325 vosStatus = WLANTL_Stop(pVosContext);
1326 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1327
Jeff Johnson295189b2012-06-20 16:38:30 -07001328 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001329 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__);
1330 /* Clean up message queues of TX and MC thread */
1331 vos_sched_flush_mc_mqs(vosSchedContext);
1332 vos_sched_flush_tx_mqs(vosSchedContext);
1333 vos_sched_flush_rx_mqs(vosSchedContext);
1334
1335 /* Deinit all the TX and MC queues */
1336 vos_sched_deinit_mqs(vosSchedContext);
1337 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__);
1338
1339 /* shutdown VOSS */
1340 vos_shutdown(pVosContext);
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05301341
1342 /*mac context has already been released in mac_close call
1343 so setting it to NULL in hdd context*/
1344 pHddCtx->hHal = (tHalHandle)NULL;
1345
Jeff Johnson295189b2012-06-20 16:38:30 -07001346 if (free_riva_power_on_lock("wlan"))
1347 {
1348 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
1349 __func__);
1350 }
1351 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete"
1352 ,__func__);
1353 return VOS_STATUS_SUCCESS;
1354}
1355
1356
1357
1358/* the HDD interface to WLAN driver re-init.
1359 * This is called to initialize/start WLAN driver after a shutdown.
1360 */
1361VOS_STATUS hdd_wlan_re_init(void)
1362{
1363 VOS_STATUS vosStatus;
1364 v_CONTEXT_t pVosContext = NULL;
1365 hdd_context_t *pHddCtx = NULL;
1366 eHalStatus halStatus;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07001367#ifdef HAVE_WCNSS_CAL_DOWNLOAD
1368 int max_retries = 0;
1369#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001370#ifdef WLAN_BTAMP_FEATURE
1371 hdd_config_t *pConfig = NULL;
1372 WLANBAP_ConfigType btAmpConfig;
1373#endif
1374
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001375 hdd_ssr_timer_del();
Jeff Johnson295189b2012-06-20 16:38:30 -07001376 hdd_prevent_suspend();
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001377
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07001378#ifdef HAVE_WCNSS_CAL_DOWNLOAD
1379 /* wait until WCNSS driver downloads NV */
1380 while (!wcnss_device_ready() && 5 >= ++max_retries) {
1381 msleep(1000);
1382 }
1383 if (max_retries >= 5) {
1384 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
1385 goto err_re_init;
1386 }
1387#endif
1388
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001389 /* The driver should always be initialized in STA mode after SSR */
1390 hdd_set_conparam(0);
1391
Jeff Johnson295189b2012-06-20 16:38:30 -07001392 /* Re-open VOSS, it is a re-open b'se control transport was never closed. */
1393 vosStatus = vos_open(&pVosContext, 0);
1394 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1395 {
1396 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
1397 goto err_re_init;
1398 }
1399
1400 /* Get the HDD context. */
1401 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1402 if(!pHddCtx)
1403 {
1404 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1405 goto err_vosclose;
1406 }
1407
1408 /* Save the hal context in Adapter */
1409 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
1410 if ( NULL == pHddCtx->hHal )
1411 {
1412 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
1413 goto err_vosclose;
1414 }
1415
1416 /* Set the SME configuration parameters. */
1417 vosStatus = hdd_set_sme_config(pHddCtx);
1418 if ( VOS_STATUS_SUCCESS != vosStatus )
1419 {
1420 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
1421 goto err_vosclose;
1422 }
1423
1424 /* Initialize the WMM module */
1425 vosStatus = hdd_wmm_init(pHddCtx);
1426 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
1427 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001428 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001429 goto err_vosclose;
1430 }
1431
1432 vosStatus = vos_preStart( pHddCtx->pvosContext );
1433 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1434 {
1435 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
1436 goto err_vosclose;
1437 }
1438
1439 /* In the integrated architecture we update the configuration from
1440 the INI file and from NV before vOSS has been started so that
1441 the final contents are available to send down to the cCPU */
1442 /* Apply the cfg.ini to cfg.dat */
1443 if (FALSE == hdd_update_config_dat(pHddCtx))
1444 {
1445 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
1446 goto err_vosclose;
1447 }
1448
1449 /* Set the MAC Address, currently this is used by HAL to add self sta.
1450 * Remove this once self sta is added as part of session open. */
1451 halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID,
1452 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
1453 sizeof(pHddCtx->cfg_ini->intfMacAddr[0]));
1454 if (!HAL_STATUS_SUCCESS(halStatus))
1455 {
1456 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
1457 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus);
1458 goto err_vosclose;
1459 }
1460
1461 /* Start VOSS which starts up the SME/MAC/HAL modules and everything else
1462 Note: Firmware image will be read and downloaded inside vos_start API */
1463 vosStatus = vos_start( pVosContext );
1464 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1465 {
1466 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
1467 goto err_vosclose;
1468 }
1469
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07001470 /* Exchange capability info between Host and FW and also get versioning info from FW */
1471 hdd_exchange_version_and_caps(pHddCtx);
1472
Jeff Johnson295189b2012-06-20 16:38:30 -07001473 vosStatus = hdd_post_voss_start_config( pHddCtx );
1474 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1475 {
1476 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
1477 __func__);
1478 goto err_vosstop;
1479 }
1480
1481#ifdef WLAN_BTAMP_FEATURE
1482 vosStatus = WLANBAP_Open(pVosContext);
1483 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1484 {
1485 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1486 "%s: Failed to open BAP",__func__);
1487 goto err_vosstop;
1488 }
1489 vosStatus = BSL_Init(pVosContext);
1490 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1491 {
1492 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1493 "%s: Failed to Init BSL",__func__);
1494 goto err_bap_close;
1495 }
1496 vosStatus = WLANBAP_Start(pVosContext);
1497 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1498 {
1499 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1500 "%s: Failed to start TL",__func__);
1501 goto err_bap_close;
1502 }
1503 pConfig = pHddCtx->cfg_ini;
1504 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
1505 vosStatus = WLANBAP_SetConfig(&btAmpConfig);
1506#endif //WLAN_BTAMP_FEATURE
1507
1508 /* Restart all adapters */
1509 hdd_start_all_adapters(pHddCtx);
1510 pHddCtx->isLogpInProgress = FALSE;
1511 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001512 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001513
1514 /* Register with platform driver as client for Suspend/Resume */
1515 vosStatus = hddRegisterPmOps(pHddCtx);
1516 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1517 {
1518 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
1519 goto err_bap_stop;
1520 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001521 /* Allow the phone to go to sleep */
1522 hdd_allow_suspend();
1523 /* register for riva power on lock */
1524 if (req_riva_power_on_lock("wlan"))
1525 {
1526 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
1527 __func__);
1528 goto err_unregister_pmops;
1529 }
1530 goto success;
1531
1532err_unregister_pmops:
1533 hddDeregisterPmOps(pHddCtx);
1534
1535err_bap_stop:
Jeff Johnson32d95a32012-09-10 13:15:23 -07001536#ifdef CONFIG_HAS_EARLYSUSPEND
1537 hdd_unregister_mcast_bcast_filter(pHddCtx);
1538#endif
1539 hdd_close_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001540#ifdef WLAN_BTAMP_FEATURE
Jeff Johnson32d95a32012-09-10 13:15:23 -07001541 WLANBAP_Stop(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07001542#endif
1543
1544#ifdef WLAN_BTAMP_FEATURE
1545err_bap_close:
1546 WLANBAP_Close(pVosContext);
1547#endif
1548
1549err_vosstop:
1550 vos_stop(pVosContext);
1551
1552err_vosclose:
1553 vos_close(pVosContext);
1554 vos_sched_close(pVosContext);
1555 if (pHddCtx)
1556 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001557 /* Unregister the Net Device Notifier */
1558 unregister_netdevice_notifier(&hdd_netdev_notifier);
1559 /* Clean up HDD Nlink Service */
1560 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1561 nl_srv_exit();
Jeff Johnson295189b2012-06-20 16:38:30 -07001562 /* Free up dynamically allocated members inside HDD Adapter */
1563 kfree(pHddCtx->cfg_ini);
1564 pHddCtx->cfg_ini= NULL;
1565
Jeff Johnson295189b2012-06-20 16:38:30 -07001566 wiphy_unregister(pHddCtx->wiphy);
1567 wiphy_free(pHddCtx->wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07001568 }
1569 vos_preClose(&pVosContext);
1570
1571#ifdef MEMORY_DEBUG
1572 vos_mem_exit();
1573#endif
1574
1575err_re_init:
1576 /* Allow the phone to go to sleep */
1577 hdd_allow_suspend();
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001578 return -EPERM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001579
1580success:
1581 /* Trigger replay of BTC events */
1582 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1583 return VOS_STATUS_SUCCESS;
1584}