blob: c5f26c62c877ac6a74d9e22e77c59667dd7e7121 [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>
Gopichand Nakkala746a9452013-06-11 12:45:54 +053094#include <net/addrconf.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070095/**-----------------------------------------------------------------------------
96* Preprocessor definitions and constants
97* ----------------------------------------------------------------------------*/
98
99/**-----------------------------------------------------------------------------
100* Type declarations
101* ----------------------------------------------------------------------------*/
102
103/**-----------------------------------------------------------------------------
104* Function and variables declarations
105* ----------------------------------------------------------------------------*/
106#include "wlan_hdd_power.h"
107#include "wlan_hdd_packet_filtering.h"
108
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -0700109#define HDD_SSR_BRING_UP_TIME 10000
Jeff Johnson295189b2012-06-20 16:38:30 -0700110
111static eHalStatus g_full_pwr_status;
112static eHalStatus g_standby_status;
113
114extern VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx);
115extern VOS_STATUS vos_chipExitDeepSleepVREGHandler(
116 vos_call_status_type* status,
117 vos_power_cb_type callback,
118 v_PVOID_t user_data);
119extern void hdd_wlan_initial_scan(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700120
121extern struct notifier_block hdd_netdev_notifier;
Jeff Johnson295189b2012-06-20 16:38:30 -0700122extern tVOS_CON_MODE hdd_get_conparam ( void );
Jeff Johnson295189b2012-06-20 16:38:30 -0700123
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -0700124static struct timer_list ssr_timer;
125static bool ssr_timer_started;
Jeff Johnson295189b2012-06-20 16:38:30 -0700126
127//Callback invoked by PMC to report status of standby request
128void hdd_suspend_standby_cbk (void *callbackContext, eHalStatus status)
129{
130 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
131 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Standby status = %d", __func__, status);
132 g_standby_status = status;
133
134 if(eHAL_STATUS_SUCCESS == status)
135 {
136 pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY;
137 }
138 else
139 {
140 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__);
141 }
142
143 complete(&pHddCtx->standby_comp_var);
144}
145
146//Callback invoked by PMC to report status of full power request
147void hdd_suspend_full_pwr_callback(void *callbackContext, eHalStatus status)
148{
149 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
150 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Full Power status = %d", __func__, status);
151 g_full_pwr_status = status;
152
153 if(eHAL_STATUS_SUCCESS == status)
154 {
155 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
156 }
157 else
158 {
159 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
160 }
161
162 complete(&pHddCtx->full_pwr_comp_var);
163}
164
165eHalStatus hdd_exit_standby(hdd_context_t *pHddCtx)
166{
167 eHalStatus status = VOS_STATUS_SUCCESS;
168
169 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from standby",__func__);
170 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
171
172 g_full_pwr_status = eHAL_STATUS_FAILURE;
173 status = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback, pHddCtx,
174 eSME_FULL_PWR_NEEDED_BY_HDD);
175
176 if(status == eHAL_STATUS_PMC_PENDING)
177 {
178 //Block on a completion variable. Can't wait forever though
179 wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var,
180 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
181 status = g_full_pwr_status;
182 if(g_full_pwr_status != eHAL_STATUS_SUCCESS)
183 {
184 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
185 VOS_ASSERT(0);
186 goto failure;
187 }
188 }
189 else if(status != eHAL_STATUS_SUCCESS)
190 {
191 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d",
192 __func__, status);
193 VOS_ASSERT(0);
194 goto failure;
195 }
196 else
197 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
198
199failure:
200 //No blocking to reduce latency. No other device should be depending on WLAN
201 //to finish resume and WLAN won't be instantly on after resume
202 return status;
203}
204
205
206//Helper routine to put the chip into standby
207VOS_STATUS hdd_enter_standby(hdd_context_t *pHddCtx)
208{
209 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
210 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
211
212 //Disable IMPS/BMPS as we do not want the device to enter any power
213 //save mode on its own during suspend sequence
214 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
215 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
216
217 //Note we do not disable queues unnecessarily. Queues should already be disabled
218 //if STA is disconnected or the queue will be disabled as and when disconnect
219 //happens because of standby procedure.
220
221 //Ensure that device is in full power first. There is scope for optimization
222 //here especially in scenarios where PMC is already in IMPS or REQUEST_IMPS.
223 //Core s/w needs to be optimized to handle this. Until then we request full
224 //power before issuing request for standby.
225 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
226 g_full_pwr_status = eHAL_STATUS_FAILURE;
227 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback,
228 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
229
230 if(halStatus == eHAL_STATUS_PMC_PENDING)
231 {
232 //Block on a completion variable. Can't wait forever though
233 wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var,
234 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
235 if(g_full_pwr_status != eHAL_STATUS_SUCCESS)
236 {
237 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower Failed",__func__);
238 VOS_ASSERT(0);
239 vosStatus = VOS_STATUS_E_FAILURE;
240 goto failure;
241 }
242 }
243 else if(halStatus != eHAL_STATUS_SUCCESS)
244 {
245 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d",
246 __func__, halStatus);
247 VOS_ASSERT(0);
248 vosStatus = VOS_STATUS_E_FAILURE;
249 goto failure;
250 }
251
252 if(pHddCtx->hdd_mcastbcast_filter_set == TRUE) {
253 hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
254 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
255 }
256
257 //Request standby. Standby will cause the STA to disassociate first. TX queues
258 //will be disabled (by HDD) when STA disconnects. You do not want to disable TX
259 //queues here. Also do not assert if the failure code is eHAL_STATUS_PMC_NOT_NOW as PMC
260 //will send this failure code in case of concurrent sessions. Power Save cannot be supported
261 //when there are concurrent sessions.
262 INIT_COMPLETION(pHddCtx->standby_comp_var);
263 g_standby_status = eHAL_STATUS_FAILURE;
264 halStatus = sme_RequestStandby(pHddCtx->hHal, hdd_suspend_standby_cbk, pHddCtx);
265
266 if (halStatus == eHAL_STATUS_PMC_PENDING)
267 {
268 //Wait till WLAN device enters standby mode
269 wait_for_completion_timeout(&pHddCtx->standby_comp_var,
270 msecs_to_jiffies(WLAN_WAIT_TIME_STANDBY));
271 if (g_standby_status != eHAL_STATUS_SUCCESS && g_standby_status != eHAL_STATUS_PMC_NOT_NOW)
272 {
273 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__);
274 VOS_ASSERT(0);
275 vosStatus = VOS_STATUS_E_FAILURE;
276 goto failure;
277 }
278 }
279 else if (halStatus != eHAL_STATUS_SUCCESS && halStatus != eHAL_STATUS_PMC_NOT_NOW) {
280 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed - status %d",
281 __func__, halStatus);
282 VOS_ASSERT(0);
283 vosStatus = VOS_STATUS_E_FAILURE;
284 goto failure;
285 }
286 else
287 pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY;
288
289failure:
290 //Restore IMPS config
291 if(pHddCtx->cfg_ini->fIsImpsEnabled)
292 sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
293
294 //Restore BMPS config
295 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
296 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
297
298 return vosStatus;
299}
300
301
302//Helper routine for Deep sleep entry
303VOS_STATUS hdd_enter_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter)
304{
305 eHalStatus halStatus;
306 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
307 vos_call_status_type callType;
Jeff Johnsonbc676b42013-02-14 16:04:08 -0800308
Jeff Johnson295189b2012-06-20 16:38:30 -0700309 //Stop the Interface TX queue.
310 netif_tx_disable(pAdapter->dev);
311 netif_carrier_off(pAdapter->dev);
312
313 //Disable IMPS,BMPS as we do not want the device to enter any power
314 //save mode on it own during suspend sequence
315 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
316 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
317
318 //Ensure that device is in full power as we will touch H/W during vos_Stop
319 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
320 g_full_pwr_status = eHAL_STATUS_FAILURE;
321 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback,
322 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
323
324 if(halStatus == eHAL_STATUS_PMC_PENDING)
325 {
326 //Block on a completion variable. Can't wait forever though
327 wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var,
328 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
329 if(g_full_pwr_status != eHAL_STATUS_SUCCESS){
330 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
331 VOS_ASSERT(0);
332 }
333 }
334 else if(halStatus != eHAL_STATUS_SUCCESS)
335 {
336 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Request for Full Power failed",__func__);
337 VOS_ASSERT(0);
338 }
339
340 //Issue a disconnect. This is required to inform the supplicant that
341 //STA is getting disassociated and for GUI to be updated properly
342 INIT_COMPLETION(pAdapter->disconnect_comp_var);
343 halStatus = sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED);
344
345 //Success implies disconnect command got queued up successfully
346 if(halStatus == eHAL_STATUS_SUCCESS)
347 {
348 //Block on a completion variable. Can't wait forever though.
349 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
350 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
351 }
352
353
354 //None of the steps should fail after this. Continue even in case of failure
355 vosStatus = vos_stop( pHddCtx->pvosContext );
356 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
357
Jeff Johnson295189b2012-06-20 16:38:30 -0700358 vosStatus = vos_chipAssertDeepSleep( &callType, NULL, NULL );
359 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
360
361 //Vote off any PMIC voltage supplies
362 vosStatus = vos_chipPowerDown(NULL, NULL, NULL);
363
Jeff Johnson295189b2012-06-20 16:38:30 -0700364 pHddCtx->hdd_ps_state = eHDD_SUSPEND_DEEP_SLEEP;
365
366 //Restore IMPS config
367 if(pHddCtx->cfg_ini->fIsImpsEnabled)
368 sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
369
370 //Restore BMPS config
371 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
372 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
373
Jeff Johnson295189b2012-06-20 16:38:30 -0700374 return vosStatus;
375}
376
377VOS_STATUS hdd_exit_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter)
378{
379 VOS_STATUS vosStatus;
380 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -0700381
382 //Power Up Libra WLAN card first if not already powered up
383 vosStatus = vos_chipPowerUp(NULL,NULL,NULL);
384 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
385 {
386 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
387 "exiting", __func__);
388 goto err_deep_sleep;
389 }
390
Jeff Johnson295189b2012-06-20 16:38:30 -0700391 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
392 "%s: calling hdd_set_sme_config",__func__);
393 vosStatus = hdd_set_sme_config( pHddCtx );
394 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
395 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
396 {
397 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
398 "%s: Failed in hdd_set_sme_config",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700399 goto err_deep_sleep;
Jeff Johnson295189b2012-06-20 16:38:30 -0700400 }
401
402 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
403 "%s: calling vos_start",__func__);
404 vosStatus = vos_start( pHddCtx->pvosContext );
405 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
406 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
407 {
408 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
409 "%s: Failed in vos_start",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700410 goto err_deep_sleep;
Jeff Johnson295189b2012-06-20 16:38:30 -0700411 }
412
413 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
414 "%s: calling hdd_post_voss_start_config",__func__);
415 vosStatus = hdd_post_voss_start_config( pHddCtx );
416 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
417 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
418 {
419 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
420 "%s: Failed in hdd_post_voss_start_config",__func__);
421 goto err_voss_stop;
422 }
423
424
425 //Open a SME session for future operation
426 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pHddCtx,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -0700427 (tANI_U8 *)&pAdapter->macAddressCurrent,
428 &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700429 if ( !HAL_STATUS_SUCCESS( halStatus ) )
430 {
431 hddLog(VOS_TRACE_LEVEL_FATAL,"sme_OpenSession() failed with status code %08d [x%08lx]",
432 halStatus, halStatus );
433 goto err_voss_stop;
434
435 }
436
437 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
438
439 //Trigger the initial scan
440 hdd_wlan_initial_scan(pHddCtx);
441
442 return VOS_STATUS_SUCCESS;
443
444err_voss_stop:
445 vos_stop(pHddCtx->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -0700446err_deep_sleep:
447 return VOS_STATUS_E_FAILURE;
448
449}
450
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530451/*
452 * Function: hdd_conf_hostoffload
453 * Central function to configure the supported offloads,
454 * either enable or disable them.
455 */
456void hdd_conf_hostoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
457{
458 hdd_context_t *pHddCtx = NULL;
459 v_CONTEXT_t *pVosContext = NULL;
460 VOS_STATUS vstatus = VOS_STATUS_E_FAILURE;
461
462 hddLog(VOS_TRACE_LEVEL_INFO, FL("Configuring offloads with flag: %d"),
463 fenable);
464
465 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
466
467 if (NULL == pVosContext)
468 {
469 hddLog(VOS_TRACE_LEVEL_ERROR, FL(" Global VOS context is Null"));
470 return;
471 }
472
473 //Get the HDD context.
474 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
475
476 if (NULL == pHddCtx)
477 {
478 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: HDD context is Null", __func__);
479 return;
480 }
481
482 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
483 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
484 {
485 if (fenable)
486 {
487 if (eConnectionState_Associated ==
488 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)
489 {
490 if ((pHddCtx->cfg_ini->fhostArpOffload))
491 {
492 /*
493 * Configure the ARP Offload.
494 * Even if it fails we have to reconfigure the MC/BC
495 * filter flag as we want RIVA not to drop BroadCast
496 * Packets
497 */
498 hddLog(VOS_TRACE_LEVEL_INFO,
499 FL("Calling ARP Offload with flag: %d"), fenable);
500 vstatus = hdd_conf_arp_offload(pAdapter, fenable);
501 pHddCtx->configuredMcastBcastFilter &=
502 ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST);
503
504 if (!VOS_IS_STATUS_SUCCESS(vstatus))
505 {
506 hddLog(VOS_TRACE_LEVEL_ERROR,
507 "Failed to enable ARPOFfloadFeature %d",
508 vstatus);
509 }
510 }
511 //Configure GTK_OFFLOAD
512#ifdef WLAN_FEATURE_GTK_OFFLOAD
513 hdd_conf_gtk_offload(pAdapter, fenable);
514#endif
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530515
516#ifdef WLAN_NS_OFFLOAD
517 if (pHddCtx->cfg_ini->fhostNSOffload)
518 {
519 /*
520 * Configure the NS Offload.
521 * Even if it fails we have to reconfigure the MC/BC filter flag
522 * as we want RIVA not to drop Multicast Packets
523 */
524
525 hddLog(VOS_TRACE_LEVEL_INFO,
526 FL("Calling NS Offload with flag: %d"), fenable);
527 hdd_conf_ns_offload(pAdapter, fenable);
528 pHddCtx->configuredMcastBcastFilter &=
529 ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST);
530 }
531#endif
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530532 }
533 }
534 else
535 {
536 //Disable ARPOFFLOAD
537 if (pHddCtx->cfg_ini->fhostArpOffload)
538 {
539 vstatus = hdd_conf_arp_offload(pAdapter, fenable);
540 if (!VOS_IS_STATUS_SUCCESS(vstatus))
541 {
542 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530543 "Failed to disable ARPOffload Feature %d", vstatus);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530544 }
545 }
546 //Disable GTK_OFFLOAD
547#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530548 hdd_conf_gtk_offload(pAdapter, fenable);
549#endif
550
551#ifdef WLAN_NS_OFFLOAD
552 //Disable NSOFFLOAD
553 if (pHddCtx->cfg_ini->fhostNSOffload)
554 {
555 hdd_conf_ns_offload(pAdapter, fenable);
556 }
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530557#endif
558 }
559 }
560 return;
561}
562
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530563#ifdef WLAN_NS_OFFLOAD
564void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
565{
566 struct inet6_dev *in6_dev;
567 struct inet6_ifaddr *ifp;
568 struct list_head *p;
569 tANI_U8 selfIPv6Addr[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA][SIR_MAC_IPV6_ADDR_LEN] = {{0,}};
570 tANI_BOOLEAN selfIPv6AddrValid[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA] = {0};
571 tSirHostOffloadReq offLoadRequest;
572
573 int i =0;
574 eHalStatus returnStatus;
575
576 ENTER();
577 if (fenable)
578 {
579 in6_dev = __in6_dev_get(pAdapter->dev);
580 if (NULL != in6_dev)
581 {
582 //read_lock_bh(&in6_dev->lock);
583 list_for_each(p, &in6_dev->addr_list)
584 {
585 ifp = list_entry(p, struct inet6_ifaddr, if_list);
586 switch(ipv6_addr_src_scope(&ifp->addr))
587 {
588 case IPV6_ADDR_SCOPE_LINKLOCAL:
589 vos_mem_copy(&selfIPv6Addr[0], &ifp->addr.s6_addr,
590 sizeof(ifp->addr.s6_addr));
591 selfIPv6AddrValid[0] = SIR_IPV6_ADDR_VALID;
592 break;
593 case IPV6_ADDR_SCOPE_GLOBAL:
594 vos_mem_copy(&selfIPv6Addr[1], &ifp->addr.s6_addr,
595 sizeof(ifp->addr.s6_addr));
596 selfIPv6AddrValid[1] = SIR_IPV6_ADDR_VALID;;
597 break;
598 default:
599 hddLog(LOGE, "The Scope %d is not supported",
600 ipv6_addr_src_scope(&ifp->addr));
601 }
602
603 }
604 //read_unlock_bh(&in6_dev->lock);
605 vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest));
606 for (i =0; i<SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA; i++)
607 {
608 if (selfIPv6AddrValid[i])
609 {
610 //Filling up the request structure
611 /* Filling the selfIPv6Addr with solicited address
612 * A Solicited-Node multicast address is created by
613 * taking the last 24 bits of a unicast or anycast
614 * address and appending them to the prefix
615 *
616 * FF02:0000:0000:0000:0000:0001:FFXX:XX
617 *
618 * here XX is the unicast/anycast bits
619 */
620 offLoadRequest.nsOffloadInfo.selfIPv6Addr[0] = 0xFF;
621 offLoadRequest.nsOffloadInfo.selfIPv6Addr[1] = 0x02;
622 offLoadRequest.nsOffloadInfo.selfIPv6Addr[11] = 0x01;
623 offLoadRequest.nsOffloadInfo.selfIPv6Addr[12] = 0xFF;
624 offLoadRequest.nsOffloadInfo.selfIPv6Addr[13] = selfIPv6Addr[i][13];
625 offLoadRequest.nsOffloadInfo.selfIPv6Addr[14] = selfIPv6Addr[i][14];
626 offLoadRequest.nsOffloadInfo.selfIPv6Addr[15] = selfIPv6Addr[i][15];
627 offLoadRequest.nsOffloadInfo.slotIdx = i;
628
629 vos_mem_copy(&offLoadRequest.nsOffloadInfo.targetIPv6Addr[0],
630 &selfIPv6Addr[i][0], sizeof(tANI_U8)*SIR_MAC_IPV6_ADDR_LEN);
631 vos_mem_copy(&offLoadRequest.nsOffloadInfo.selfMacAddr,
632 &pAdapter->macAddressCurrent.bytes,
633 sizeof(tANI_U8)*SIR_MAC_ADDR_LEN);
634
635 offLoadRequest.nsOffloadInfo.targetIPv6AddrValid[0] = SIR_IPV6_ADDR_VALID;
636 offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD;
637 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
638
639 vos_mem_copy(&offLoadRequest.params.hostIpv6Addr,
640 &offLoadRequest.nsOffloadInfo.targetIPv6Addr[0],
641 sizeof(tANI_U8)*SIR_MAC_IPV6_ADDR_LEN);
642
643 hddLog (VOS_TRACE_LEVEL_INFO,
644 "Setting NSOffload with solicitedIp: %pI6, targetIp: %pI6",
645 offLoadRequest.nsOffloadInfo.selfIPv6Addr,
646 offLoadRequest.nsOffloadInfo.targetIPv6Addr[0]);
647
648 //Configure the Firmware with this
649 returnStatus = sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
650 pAdapter->sessionId, &offLoadRequest);
651 if(eHAL_STATUS_SUCCESS != returnStatus)
652 {
653 hddLog(VOS_TRACE_LEVEL_ERROR,
654 FL("Failed to enable HostOffload feature with status: %d"),
655 returnStatus);
656 }
657 vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest));
658 }
659 }
660 }
661 else
662 {
663 hddLog(VOS_TRACE_LEVEL_ERROR,
664 FL("IPv6 dev does not exist. Failed to request NSOffload"));
665 return;
666 }
667 }
668 else
669 {
670 //Disable NSOffload
671 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
672 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
673 offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD;
674
675 if (eHAL_STATUS_SUCCESS !=
676 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
677 pAdapter->sessionId, &offLoadRequest))
678 {
679 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failure to disable"
680 "NSOffload feature"));
681 }
682 }
683 return;
684}
685#endif
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530686VOS_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
Jeff Johnson295189b2012-06-20 16:38:30 -0700687{
688 struct in_ifaddr **ifap = NULL;
689 struct in_ifaddr *ifa = NULL;
690 struct in_device *in_dev;
691 int i = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700692 tSirHostOffloadReq offLoadRequest;
Yathish9f22e662012-12-10 14:21:35 -0800693 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700694
695 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700696
Jeff Johnson295189b2012-06-20 16:38:30 -0700697 if(fenable)
698 {
699 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
700 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530701 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700702 ifap = &ifa->ifa_next)
703 {
704 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
705 {
706 break; /* found */
707 }
708 }
709 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700710 if(ifa && ifa->ifa_local)
711 {
712 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
713 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
714
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530715 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Enabled \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700716
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530717 if((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
718 pHddCtx->configuredMcastBcastFilter) ||
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700719 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530720 pHddCtx->configuredMcastBcastFilter))
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700721 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530722 offLoadRequest.enableOrDisable =
723 SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700724 }
725
726 //converting u32 to IPV4 address
727 for(i = 0 ; i < 4; i++)
728 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530729 offLoadRequest.params.hostIpv4Addr[i] =
Jeff Johnson295189b2012-06-20 16:38:30 -0700730 (ifa->ifa_local >> (i*8) ) & 0xFF ;
731 }
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530732 hddLog(VOS_TRACE_LEVEL_INFO, " Enable SME HostOffload: %d.%d.%d.%d",
Jeff Johnson295189b2012-06-20 16:38:30 -0700733 offLoadRequest.params.hostIpv4Addr[0],
734 offLoadRequest.params.hostIpv4Addr[1],
735 offLoadRequest.params.hostIpv4Addr[2],
736 offLoadRequest.params.hostIpv4Addr[3]);
737
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530738 if (eHAL_STATUS_SUCCESS !=
739 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
740 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700741 {
742 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to enable HostOffload "
743 "feature\n", __func__);
744 return VOS_STATUS_E_FAILURE;
745 }
746 return VOS_STATUS_SUCCESS;
747 }
748 else
749 {
750 hddLog(VOS_TRACE_LEVEL_INFO, "%s:IP Address is not assigned \n", __func__);
751 return VOS_STATUS_E_AGAIN;
752 }
753 }
754 else
755 {
756 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
757 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
758 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
759
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530760 if (eHAL_STATUS_SUCCESS !=
761 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
762 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700763 {
764 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to disable host "
765 "offload feature\n", __func__);
766 return VOS_STATUS_E_FAILURE;
767 }
768 return VOS_STATUS_SUCCESS;
769 }
770}
771
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530772/*
773 * This function is called before setting mcbc filters
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530774 * to modify filter value considering Different Offloads
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530775*/
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530776void hdd_mcbc_filter_modification(hdd_context_t* pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530777 tANI_U8 *pMcBcFilter)
778{
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530779 if (NULL == pHddCtx)
780 {
781 hddLog(VOS_TRACE_LEVEL_ERROR, FL("NULL HDD context passed"));
782 return;
783 }
784
785 *pMcBcFilter = pHddCtx->configuredMcastBcastFilter;
786 if (pHddCtx->cfg_ini->fhostArpOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530787 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530788 /* ARP offload is enabled, do not block bcast packets at RXP
789 * Will be using Bitmasking to reset the filter. As we have
790 * disable Broadcast filtering, Anding with the negation
791 * of Broadcast BIT
792 */
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530793 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530794 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530795
796#ifdef WLAN_NS_OFFLOAD
797 if (pHddCtx->cfg_ini->fhostNSOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530798 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530799 /* NS offload is enabled, do not block mcast packets at RXP
800 * Will be using Bitmasking to reset the filter. As we have
801 * disable Multicast filtering, Anding with the negation
802 * of Multicast BIT
803 */
804 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530805 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530806#endif
807
808 pHddCtx->configuredMcastBcastFilter = *pMcBcFilter;
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530809}
810
Jeff Johnson295189b2012-06-20 16:38:30 -0700811void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter)
812{
813 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700814 tpSirWlanSetRxpFilters wlanRxpFilterParam =
815 vos_mem_malloc(sizeof(tSirWlanSetRxpFilters));
816 if(NULL == wlanRxpFilterParam)
817 {
818 hddLog(VOS_TRACE_LEVEL_FATAL,
819 "%s: vos_mem_alloc failed ", __func__);
820 return;
821 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700822 hddLog(VOS_TRACE_LEVEL_INFO,
823 "%s: Configuring Mcast/Bcast Filter Setting. setfilter %d", __func__, setfilter);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530824 if (TRUE == setfilter)
825 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530826 hdd_mcbc_filter_modification(pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530827 &wlanRxpFilterParam->configuredMcstBcstFilterSetting);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530828 }
829 else
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530830 {
831 /*Use the current configured value to clear*/
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530832 wlanRxpFilterParam->configuredMcstBcstFilterSetting =
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530833 pHddCtx->configuredMcastBcastFilter;
834 }
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530835
Jeff Johnson295189b2012-06-20 16:38:30 -0700836 wlanRxpFilterParam->setMcstBcstFilter = setfilter;
Jeff Johnson295189b2012-06-20 16:38:30 -0700837 halStatus = sme_ConfigureRxpFilter(pHddCtx->hHal, wlanRxpFilterParam);
Chilam Ngc4244af2013-04-01 15:37:32 -0700838 if (eHAL_STATUS_SUCCESS != halStatus)
839 vos_mem_free(wlanRxpFilterParam);
Jeff Johnson295189b2012-06-20 16:38:30 -0700840 if(setfilter && (eHAL_STATUS_SUCCESS == halStatus))
841 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
842}
843
Jeff Johnson295189b2012-06-20 16:38:30 -0700844static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx,
845 hdd_adapter_t *pAdapter)
846{
847 eHalStatus halStatus = eHAL_STATUS_FAILURE;
848 tpSirWlanSuspendParam wlanSuspendParam =
849 vos_mem_malloc(sizeof(tSirWlanSuspendParam));
850
851 if(NULL == wlanSuspendParam)
852 {
853 hddLog(VOS_TRACE_LEVEL_FATAL,
854 "%s: vos_mem_alloc failed ", __func__);
855 return;
856 }
857
858 hddLog(VOS_TRACE_LEVEL_INFO,
859 "%s: send wlan suspend indication", __func__);
860
861 if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER))
862 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530863 //Configure supported OffLoads
864 hdd_conf_hostoffload(pAdapter, TRUE);
865 wlanSuspendParam->configuredMcstBcstFilterSetting = pHddCtx->configuredMcastBcastFilter;
Jeff Johnson295189b2012-06-20 16:38:30 -0700866
867#ifdef WLAN_FEATURE_PACKET_FILTERING
madan mohan koyyalamudibfd9cef2013-07-01 18:39:37 +0530868 /* During suspend, configure MC Addr list filter to the firmware
869 * function takes care of checking necessary conditions before
870 * configuring.
871 */
872 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700873#endif
874 }
875
876 halStatus = sme_ConfigureSuspendInd(pHddCtx->hHal, wlanSuspendParam);
877 if(eHAL_STATUS_SUCCESS == halStatus)
878 {
879 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
Chilam Ngc4244af2013-04-01 15:37:32 -0700880 } else {
881 vos_mem_free(wlanSuspendParam);
Jeff Johnson295189b2012-06-20 16:38:30 -0700882 }
883}
884
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530885static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700886{
Chilam Ngc4244af2013-04-01 15:37:32 -0700887 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Yathish9f22e662012-12-10 14:21:35 -0800888 hdd_context_t* pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Chilam Ngc4244af2013-04-01 15:37:32 -0700889 tpSirWlanResumeParam wlanResumeParam;
Jeff Johnson295189b2012-06-20 16:38:30 -0700890
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530891 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700892 "%s: send wlan resume indication", __func__);
893
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530894 if (pHddCtx->hdd_mcastbcast_filter_set == TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -0700895 {
Chilam Ngc4244af2013-04-01 15:37:32 -0700896 wlanResumeParam = vos_mem_malloc(sizeof(tSirWlanResumeParam));
897
898 if(NULL == wlanResumeParam)
899 {
900 hddLog(VOS_TRACE_LEVEL_FATAL,
901 "%s: vos_mem_alloc failed ", __func__);
902 return;
903 }
904
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530905 //Disable supported OffLoads
906 hdd_conf_hostoffload(pAdapter, FALSE);
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530907
908 wlanResumeParam->configuredMcstBcstFilterSetting =
909 pHddCtx->configuredMcastBcastFilter;
Chilam Ngc4244af2013-04-01 15:37:32 -0700910 halStatus = sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam);
911 if (eHAL_STATUS_SUCCESS != halStatus)
912 vos_mem_free(wlanResumeParam);
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530913 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700914 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700915
Chilam Ngc4244af2013-04-01 15:37:32 -0700916
madan mohan koyyalamudibfd9cef2013-07-01 18:39:37 +0530917#ifdef WLAN_FEATURE_PACKET_FILTERING
918 /* Filer was applied during suspend inditication
919 * clear it when we resume.
920 */
921 wlan_hdd_set_mc_addr_list(pAdapter, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700922#endif
923}
Jeff Johnson295189b2012-06-20 16:38:30 -0700924
Jeff Johnson295189b2012-06-20 16:38:30 -0700925//Suspend routine registered with Android OS
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800926void hdd_suspend_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -0700927{
928 hdd_context_t *pHddCtx = NULL;
929 v_CONTEXT_t pVosContext = NULL;
930
Jeff Johnson295189b2012-06-20 16:38:30 -0700931 VOS_STATUS status;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +0530932 hdd_adapter_t *pAdapter = NULL;
933 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +0530934 bool hdd_enter_bmps = FALSE;
Jeff Johnsonbc676b42013-02-14 16:04:08 -0800935
Jeff Johnson295189b2012-06-20 16:38:30 -0700936 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__);
937
938 //Get the global VOSS context.
939 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
940 if(!pVosContext) {
941 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
942 return;
943 }
944
945 //Get the HDD context.
946 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
947
948 if(!pHddCtx) {
949 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
950 return;
951 }
952
953 if (pHddCtx->isLogpInProgress) {
954 hddLog(VOS_TRACE_LEVEL_ERROR,
955 "%s: Ignore suspend wlan, LOGP in progress!", __func__);
956 return;
957 }
958
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +0530959 hdd_set_pwrparams(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700960 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
961 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
962 {
963 pAdapter = pAdapterNode->pAdapter;
964 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -0700965 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -0700966 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
967
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -0700968 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -0700969 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
970 pAdapterNode = pNext;
971 continue;
972 }
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +0530973 /* Avoid multiple enter/exit BMPS in this while loop using
974 * hdd_enter_bmps flag
975 */
976 if (FALSE == hdd_enter_bmps && (BMPS == pmcGetPmcState(pHddCtx->hHal)))
977 {
978 hdd_enter_bmps = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700979
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +0530980 /* If device was already in BMPS, and dynamic DTIM is set,
981 * exit(set the device to full power) and enter BMPS again
982 * to reflect new DTIM value */
983 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
984
985 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
986
987 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
988 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700989#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
990 if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
991 {
992 //stop the interface before putting the chip to standby
993 netif_tx_disable(pAdapter->dev);
994 netif_carrier_off(pAdapter->dev);
995 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +0530996 else if (pHddCtx->cfg_ini->nEnableSuspend ==
Jeff Johnson295189b2012-06-20 16:38:30 -0700997 WLAN_MAP_SUSPEND_TO_DEEP_SLEEP)
998 {
999 //Execute deep sleep procedure
1000 hdd_enter_deep_sleep(pHddCtx, pAdapter);
1001 }
1002#endif
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301003
1004 /*Suspend notification sent down to driver*/
1005 hdd_conf_suspend_ind(pHddCtx, pAdapter);
1006
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301007 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1008 pAdapterNode = pNext;
1009 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301010 pHddCtx->hdd_wlan_suspended = TRUE;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301011
Jeff Johnson295189b2012-06-20 16:38:30 -07001012#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1013 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1014 {
1015 hdd_enter_standby(pHddCtx);
1016 }
1017#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001018
1019 return;
1020}
1021
1022static void hdd_PowerStateChangedCB
1023(
1024 v_PVOID_t callbackContext,
1025 tPmcState newState
1026)
1027{
1028 hdd_context_t *pHddCtx = callbackContext;
1029
1030 /* if the driver was not in BMPS during early suspend,
1031 * the dynamic DTIM is now updated at Riva */
1032 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended
1033 && pHddCtx->cfg_ini->enableDynamicDTIM
1034 && (pHddCtx->hdd_ignore_dtim_enabled == FALSE))
1035 {
1036 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1037 }
1038 spin_lock(&pHddCtx->filter_lock);
Gopichand Nakkalac1b11522013-03-25 15:25:33 +05301039 if((newState == BMPS) && pHddCtx->hdd_wlan_suspended) {
Jeff Johnson295189b2012-06-20 16:38:30 -07001040 spin_unlock(&pHddCtx->filter_lock);
1041 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001042 if(pHddCtx->hdd_mcastbcast_filter_set != TRUE)
1043 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__);
1044 }
1045 else
1046 spin_unlock(&pHddCtx->filter_lock);
1047}
1048
1049
1050
1051void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx)
1052{
1053 v_CONTEXT_t pVosContext;
1054 tHalHandle smeContext;
1055
1056 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1057 if (NULL == pVosContext)
1058 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001059 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001060 return;
1061 }
1062 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1063 if (NULL == smeContext)
1064 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001065 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001066 return;
1067 }
1068
1069 spin_lock_init(&pHddCtx->filter_lock);
1070 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1071 pHddCtx->cfg_ini->nEnableSuspend)
1072 {
1073 pmcRegisterDeviceStateUpdateInd(smeContext,
1074 hdd_PowerStateChangedCB, pHddCtx);
1075 }
1076}
1077
1078void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx)
1079{
1080 v_CONTEXT_t pVosContext;
1081 tHalHandle smeContext;
1082
1083 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1084 if (NULL == pVosContext)
1085 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001086 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001087 return;
1088 }
1089 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1090 if (NULL == smeContext)
1091 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001092 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001093 return;
1094 }
1095
1096 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1097 pHddCtx->cfg_ini->nEnableSuspend)
1098 {
1099 pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB);
1100 }
1101}
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301102
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301103#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301104void hdd_conf_gtk_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301105{
1106 eHalStatus ret;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301107 tSirGtkOffloadParams hddGtkOffloadReqParams;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301108 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1109
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301110 if(fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301111 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301112 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1113 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags ))
1114 {
1115 vos_mem_copy(&hddGtkOffloadReqParams,
1116 &pHddStaCtx->gtkOffloadReqParams,
1117 sizeof (tSirGtkOffloadParams));
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301118
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301119 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1120 &hddGtkOffloadReqParams, pAdapter->sessionId);
1121 if (eHAL_STATUS_SUCCESS != ret)
1122 {
1123 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1124 "%s: sme_SetGTKOffload failed, returned %d",
1125 __func__, ret);
1126 return;
1127 }
1128
1129 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1130 "%s: sme_SetGTKOffload successfull", __func__);
1131 }
1132
1133 }
1134 else
1135 {
1136 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1137 (0 == memcmp(&pHddStaCtx->gtkOffloadReqParams.bssId,
1138 &pHddStaCtx->conn_info.bssId, WNI_CFG_BSSID_LEN)) &&
1139 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags))
1140 {
1141
1142 /* Host driver has previously offloaded GTK rekey */
1143 ret = sme_GetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301144 wlan_hdd_cfg80211_update_replayCounterCallback,
1145 pAdapter, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301146 if (eHAL_STATUS_SUCCESS != ret)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301147
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301148 {
1149 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1150 "%s: sme_GetGTKOffload failed, returned %d",
1151 __func__, ret);
1152 return;
1153 }
1154 else
1155 {
1156 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1157 "%s: sme_GetGTKOffload successful",
1158 __func__);
1159
1160 /* Sending GTK offload dissable */
1161 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
1162 sizeof (tSirGtkOffloadParams));
1163 hddGtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE;
1164 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301165 &hddGtkOffloadReqParams, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301166 if (eHAL_STATUS_SUCCESS != ret)
1167 {
1168 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1169 "%s: failed to dissable GTK offload, returned %d",
1170 __func__, ret);
1171 return;
1172 }
1173 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1174 "%s: successfully dissabled GTK offload request to HAL",
1175 __func__);
1176 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301177 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301178 }
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301179 return;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301180}
1181#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
Jeff Johnson295189b2012-06-20 16:38:30 -07001182
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001183void hdd_resume_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001184{
1185 hdd_context_t *pHddCtx = NULL;
1186 hdd_adapter_t *pAdapter = NULL;
1187 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1188 VOS_STATUS status;
1189 v_CONTEXT_t pVosContext = NULL;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001190
Jeff Johnson295189b2012-06-20 16:38:30 -07001191 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
1192
1193 //Get the global VOSS context.
1194 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1195 if(!pVosContext) {
1196 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1197 return;
1198 }
1199
1200 //Get the HDD context.
1201 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1202
1203 if(!pHddCtx) {
1204 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1205 return;
1206 }
1207
1208 if (pHddCtx->isLogpInProgress) {
1209 hddLog(VOS_TRACE_LEVEL_INFO,
1210 "%s: Ignore resume wlan, LOGP in progress!", __func__);
1211 return;
1212 }
1213
Jeff Johnson295189b2012-06-20 16:38:30 -07001214 pHddCtx->hdd_wlan_suspended = FALSE;
1215 /*loop through all adapters. Concurrency */
1216 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1217
1218 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1219 {
1220 pAdapter = pAdapterNode->pAdapter;
1221 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001222 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001223 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001224 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001225 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1226 pAdapterNode = pNext;
1227 continue;
1228 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301229
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301230
Jeff Johnson295189b2012-06-20 16:38:30 -07001231#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1232 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP)
1233 {
1234 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__);
1235 hdd_exit_deep_sleep(pAdapter);
1236 }
1237#endif
1238
1239 if(pHddCtx->hdd_ignore_dtim_enabled == TRUE)
1240 {
1241 /*Switch back to DTIM 1*/
1242 tSirSetPowerParamsReq powerRequest = { 0 };
1243
1244 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
1245 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07001246 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001247
1248 /*Disabled ModulatedDTIM if enabled on suspend*/
1249 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1250 powerRequest.uDTIMPeriod = 0;
1251
1252 /* Update ignoreDTIM and ListedInterval in CFG with default values */
1253 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1254 NULL, eANI_BOOLEAN_FALSE);
1255 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1256 NULL, eANI_BOOLEAN_FALSE);
1257
1258 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1259 "Switch to DTIM%d \n",powerRequest.uListenInterval);
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08001260 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001261
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301262 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
1263 {
1264 /* put the device into full power */
1265 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001266
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301267 /* put the device back into BMPS */
1268 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
Jeff Johnson295189b2012-06-20 16:38:30 -07001269
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301270 pHddCtx->hdd_ignore_dtim_enabled = FALSE;
1271 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001272 }
1273
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301274 hdd_conf_resume_ind(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001275 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1276 pAdapterNode = pNext;
1277 }
1278
1279#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1280 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY)
1281 {
1282 hdd_exit_standby(pHddCtx);
1283 }
1284#endif
1285
Jeff Johnson295189b2012-06-20 16:38:30 -07001286 return;
1287}
1288
Jeff Johnson295189b2012-06-20 16:38:30 -07001289VOS_STATUS hdd_wlan_reset_initialization(void)
1290{
Jeff Johnson295189b2012-06-20 16:38:30 -07001291 v_CONTEXT_t pVosContext = NULL;
1292
1293 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1294
1295 //Get the global VOSS context.
1296 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1297 if(!pVosContext)
1298 {
1299 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1300 return VOS_STATUS_E_FAILURE;
1301 }
1302
1303 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__);
1304
1305 // Prevent the phone from going to sleep
1306 hdd_prevent_suspend();
1307
Jeff Johnson295189b2012-06-20 16:38:30 -07001308 return VOS_STATUS_SUCCESS;
1309}
1310
1311
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001312/*
1313 * Based on the ioctl command recieved by HDD, put WLAN driver
1314 * into the quiet mode. This is the same as the early suspend
1315 * notification that driver used to listen
1316 */
1317void hdd_set_wlan_suspend_mode(bool suspend)
Jeff Johnson295189b2012-06-20 16:38:30 -07001318{
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001319 if (suspend)
1320 hdd_suspend_wlan();
1321 else
1322 hdd_resume_wlan();
Jeff Johnson295189b2012-06-20 16:38:30 -07001323}
1324
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001325static void hdd_ssr_timer_init(void)
1326{
1327 init_timer(&ssr_timer);
1328}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001329
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001330static void hdd_ssr_timer_del(void)
1331{
1332 del_timer(&ssr_timer);
1333 ssr_timer_started = false;
1334}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001335
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001336static void hdd_ssr_timer_cb(unsigned long data)
1337{
1338 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD SSR timer expired", __func__);
1339 VOS_BUG(0);
1340}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001341
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001342static void hdd_ssr_timer_start(int msec)
1343{
1344 if(ssr_timer_started)
1345 {
1346 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: trying to start SSR timer when it's running"
1347 ,__func__);
1348 }
1349 ssr_timer.expires = jiffies + msecs_to_jiffies(msec);
1350 ssr_timer.function = hdd_ssr_timer_cb;
1351 add_timer(&ssr_timer);
1352 ssr_timer_started = true;
1353}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001354
Jeff Johnson295189b2012-06-20 16:38:30 -07001355/* the HDD interface to WLAN driver shutdown,
1356 * the primary shutdown function in SSR
1357 */
1358VOS_STATUS hdd_wlan_shutdown(void)
1359{
1360 VOS_STATUS vosStatus;
1361 v_CONTEXT_t pVosContext = NULL;
1362 hdd_context_t *pHddCtx = NULL;
1363 pVosSchedContext vosSchedContext = NULL;
1364
1365 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__);
1366
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001367 /* if re-init never happens, then do SSR1 */
1368 hdd_ssr_timer_init();
1369 hdd_ssr_timer_start(HDD_SSR_BRING_UP_TIME);
1370
Jeff Johnson295189b2012-06-20 16:38:30 -07001371 /* Get the global VOSS context. */
1372 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1373 if(!pVosContext) {
1374 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1375 return VOS_STATUS_E_FAILURE;
1376 }
1377 /* Get the HDD context. */
1378 pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1379 if(!pHddCtx) {
1380 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1381 return VOS_STATUS_E_FAILURE;
1382 }
1383 hdd_reset_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001384 /* DeRegister with platform driver as client for Suspend/Resume */
1385 vosStatus = hddDeregisterPmOps(pHddCtx);
1386 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1387 {
1388 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
1389 }
1390
1391 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
1392 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1393 {
1394 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
1395 }
1396
1397 /* Disable IMPS/BMPS as we do not want the device to enter any power
1398 * save mode on its own during reset sequence
1399 */
1400 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1401 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1402 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1403
1404 vosSchedContext = get_vos_sched_ctxt();
1405
1406 /* Wakeup all driver threads */
1407 if(TRUE == pHddCtx->isMcThreadSuspended){
1408 complete(&vosSchedContext->ResumeMcEvent);
1409 pHddCtx->isMcThreadSuspended= FALSE;
1410 }
1411 if(TRUE == pHddCtx->isTxThreadSuspended){
1412 complete(&vosSchedContext->ResumeTxEvent);
1413 pHddCtx->isTxThreadSuspended= FALSE;
1414 }
1415 if(TRUE == pHddCtx->isRxThreadSuspended){
1416 complete(&vosSchedContext->ResumeRxEvent);
1417 pHddCtx->isRxThreadSuspended= FALSE;
1418 }
1419 /* Reset the Suspend Variable */
1420 pHddCtx->isWlanSuspended = FALSE;
1421
1422 /* Stop all the threads; we do not want any messages to be a processed,
1423 * any more and the best way to ensure that is to terminate the threads
1424 * gracefully.
1425 */
1426 /* Wait for MC to exit */
1427 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
1428 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
1429 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
1430 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
1431 wait_for_completion_interruptible(&vosSchedContext->McShutdown);
1432
1433 /* Wait for TX to exit */
1434 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
1435 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
1436 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
1437 wake_up_interruptible(&vosSchedContext->txWaitQueue);
1438 wait_for_completion_interruptible(&vosSchedContext->TxShutdown);
1439
1440 /* Wait for RX to exit */
1441 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
1442 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
1443 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
1444 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
1445 wait_for_completion_interruptible(&vosSchedContext->RxShutdown);
1446
1447#ifdef WLAN_BTAMP_FEATURE
1448 vosStatus = WLANBAP_Stop(pVosContext);
1449 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1450 {
1451 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1452 "%s: Failed to stop BAP",__func__);
1453 }
1454#endif //WLAN_BTAMP_FEATURE
1455 vosStatus = vos_wda_shutdown(pVosContext);
1456 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1457
1458 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
1459 /* Stop SME - Cannot invoke vos_stop as vos_stop relies
1460 * on threads being running to process the SYS Stop
1461 */
1462 vosStatus = sme_Stop(pHddCtx->hHal, TRUE);
1463 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1464
1465 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
1466 /* Stop MAC (PE and HAL) */
1467 vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
1468 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1469
1470 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
1471 /* Stop TL */
1472 vosStatus = WLANTL_Stop(pVosContext);
1473 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1474
Jeff Johnson295189b2012-06-20 16:38:30 -07001475 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001476 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__);
1477 /* Clean up message queues of TX and MC thread */
1478 vos_sched_flush_mc_mqs(vosSchedContext);
1479 vos_sched_flush_tx_mqs(vosSchedContext);
1480 vos_sched_flush_rx_mqs(vosSchedContext);
1481
1482 /* Deinit all the TX and MC queues */
1483 vos_sched_deinit_mqs(vosSchedContext);
1484 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__);
1485
1486 /* shutdown VOSS */
1487 vos_shutdown(pVosContext);
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05301488
1489 /*mac context has already been released in mac_close call
1490 so setting it to NULL in hdd context*/
1491 pHddCtx->hHal = (tHalHandle)NULL;
1492
Jeff Johnson295189b2012-06-20 16:38:30 -07001493 if (free_riva_power_on_lock("wlan"))
1494 {
1495 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
1496 __func__);
1497 }
1498 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete"
1499 ,__func__);
1500 return VOS_STATUS_SUCCESS;
1501}
1502
1503
1504
1505/* the HDD interface to WLAN driver re-init.
1506 * This is called to initialize/start WLAN driver after a shutdown.
1507 */
1508VOS_STATUS hdd_wlan_re_init(void)
1509{
1510 VOS_STATUS vosStatus;
1511 v_CONTEXT_t pVosContext = NULL;
1512 hdd_context_t *pHddCtx = NULL;
1513 eHalStatus halStatus;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07001514#ifdef HAVE_WCNSS_CAL_DOWNLOAD
1515 int max_retries = 0;
1516#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001517#ifdef WLAN_BTAMP_FEATURE
1518 hdd_config_t *pConfig = NULL;
1519 WLANBAP_ConfigType btAmpConfig;
1520#endif
1521
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001522 hdd_ssr_timer_del();
Jeff Johnson295189b2012-06-20 16:38:30 -07001523 hdd_prevent_suspend();
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001524
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07001525#ifdef HAVE_WCNSS_CAL_DOWNLOAD
1526 /* wait until WCNSS driver downloads NV */
1527 while (!wcnss_device_ready() && 5 >= ++max_retries) {
1528 msleep(1000);
1529 }
1530 if (max_retries >= 5) {
1531 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
1532 goto err_re_init;
1533 }
1534#endif
1535
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001536 /* The driver should always be initialized in STA mode after SSR */
1537 hdd_set_conparam(0);
1538
Jeff Johnson295189b2012-06-20 16:38:30 -07001539 /* Re-open VOSS, it is a re-open b'se control transport was never closed. */
1540 vosStatus = vos_open(&pVosContext, 0);
1541 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1542 {
1543 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
1544 goto err_re_init;
1545 }
1546
1547 /* Get the HDD context. */
1548 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1549 if(!pHddCtx)
1550 {
1551 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1552 goto err_vosclose;
1553 }
1554
1555 /* Save the hal context in Adapter */
1556 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
1557 if ( NULL == pHddCtx->hHal )
1558 {
1559 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
1560 goto err_vosclose;
1561 }
1562
1563 /* Set the SME configuration parameters. */
1564 vosStatus = hdd_set_sme_config(pHddCtx);
1565 if ( VOS_STATUS_SUCCESS != vosStatus )
1566 {
1567 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
1568 goto err_vosclose;
1569 }
1570
1571 /* Initialize the WMM module */
1572 vosStatus = hdd_wmm_init(pHddCtx);
1573 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
1574 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001575 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001576 goto err_vosclose;
1577 }
1578
1579 vosStatus = vos_preStart( pHddCtx->pvosContext );
1580 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1581 {
1582 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
1583 goto err_vosclose;
1584 }
1585
1586 /* In the integrated architecture we update the configuration from
1587 the INI file and from NV before vOSS has been started so that
1588 the final contents are available to send down to the cCPU */
1589 /* Apply the cfg.ini to cfg.dat */
1590 if (FALSE == hdd_update_config_dat(pHddCtx))
1591 {
1592 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
1593 goto err_vosclose;
1594 }
1595
1596 /* Set the MAC Address, currently this is used by HAL to add self sta.
1597 * Remove this once self sta is added as part of session open. */
1598 halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID,
1599 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
1600 sizeof(pHddCtx->cfg_ini->intfMacAddr[0]));
1601 if (!HAL_STATUS_SUCCESS(halStatus))
1602 {
1603 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
1604 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus);
1605 goto err_vosclose;
1606 }
1607
1608 /* Start VOSS which starts up the SME/MAC/HAL modules and everything else
1609 Note: Firmware image will be read and downloaded inside vos_start API */
1610 vosStatus = vos_start( pVosContext );
1611 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1612 {
1613 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
1614 goto err_vosclose;
1615 }
1616
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07001617 /* Exchange capability info between Host and FW and also get versioning info from FW */
1618 hdd_exchange_version_and_caps(pHddCtx);
1619
Jeff Johnson295189b2012-06-20 16:38:30 -07001620 vosStatus = hdd_post_voss_start_config( pHddCtx );
1621 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1622 {
1623 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
1624 __func__);
1625 goto err_vosstop;
1626 }
1627
1628#ifdef WLAN_BTAMP_FEATURE
1629 vosStatus = WLANBAP_Open(pVosContext);
1630 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1631 {
1632 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1633 "%s: Failed to open BAP",__func__);
1634 goto err_vosstop;
1635 }
1636 vosStatus = BSL_Init(pVosContext);
1637 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1638 {
1639 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1640 "%s: Failed to Init BSL",__func__);
1641 goto err_bap_close;
1642 }
1643 vosStatus = WLANBAP_Start(pVosContext);
1644 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1645 {
1646 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1647 "%s: Failed to start TL",__func__);
1648 goto err_bap_close;
1649 }
1650 pConfig = pHddCtx->cfg_ini;
1651 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
1652 vosStatus = WLANBAP_SetConfig(&btAmpConfig);
1653#endif //WLAN_BTAMP_FEATURE
1654
1655 /* Restart all adapters */
1656 hdd_start_all_adapters(pHddCtx);
1657 pHddCtx->isLogpInProgress = FALSE;
1658 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001659 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001660
1661 /* Register with platform driver as client for Suspend/Resume */
1662 vosStatus = hddRegisterPmOps(pHddCtx);
1663 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1664 {
1665 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
1666 goto err_bap_stop;
1667 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001668 /* Allow the phone to go to sleep */
1669 hdd_allow_suspend();
1670 /* register for riva power on lock */
1671 if (req_riva_power_on_lock("wlan"))
1672 {
1673 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
1674 __func__);
1675 goto err_unregister_pmops;
1676 }
1677 goto success;
1678
1679err_unregister_pmops:
1680 hddDeregisterPmOps(pHddCtx);
1681
1682err_bap_stop:
Jeff Johnson32d95a32012-09-10 13:15:23 -07001683#ifdef CONFIG_HAS_EARLYSUSPEND
1684 hdd_unregister_mcast_bcast_filter(pHddCtx);
1685#endif
1686 hdd_close_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001687#ifdef WLAN_BTAMP_FEATURE
Jeff Johnson32d95a32012-09-10 13:15:23 -07001688 WLANBAP_Stop(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07001689#endif
1690
1691#ifdef WLAN_BTAMP_FEATURE
1692err_bap_close:
1693 WLANBAP_Close(pVosContext);
1694#endif
1695
1696err_vosstop:
1697 vos_stop(pVosContext);
1698
1699err_vosclose:
1700 vos_close(pVosContext);
1701 vos_sched_close(pVosContext);
1702 if (pHddCtx)
1703 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001704 /* Unregister the Net Device Notifier */
1705 unregister_netdevice_notifier(&hdd_netdev_notifier);
1706 /* Clean up HDD Nlink Service */
1707 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1708 nl_srv_exit();
Jeff Johnson295189b2012-06-20 16:38:30 -07001709 /* Free up dynamically allocated members inside HDD Adapter */
1710 kfree(pHddCtx->cfg_ini);
1711 pHddCtx->cfg_ini= NULL;
1712
Jeff Johnson295189b2012-06-20 16:38:30 -07001713 wiphy_unregister(pHddCtx->wiphy);
1714 wiphy_free(pHddCtx->wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07001715 }
1716 vos_preClose(&pVosContext);
1717
1718#ifdef MEMORY_DEBUG
1719 vos_mem_exit();
1720#endif
1721
1722err_re_init:
1723 /* Allow the phone to go to sleep */
1724 hdd_allow_suspend();
Sameer Thalappil451ebb92013-06-28 15:49:58 -07001725 VOS_BUG(0);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001726 return -EPERM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001727
1728success:
1729 /* Trigger replay of BTC events */
1730 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1731 return VOS_STATUS_SUCCESS;
1732}