blob: 8ebb44785550bba0a358f3229ae1387c13d553af [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,
427 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
428 if ( !HAL_STATUS_SUCCESS( halStatus ) )
429 {
430 hddLog(VOS_TRACE_LEVEL_FATAL,"sme_OpenSession() failed with status code %08d [x%08lx]",
431 halStatus, halStatus );
432 goto err_voss_stop;
433
434 }
435
436 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
437
438 //Trigger the initial scan
439 hdd_wlan_initial_scan(pHddCtx);
440
441 return VOS_STATUS_SUCCESS;
442
443err_voss_stop:
444 vos_stop(pHddCtx->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -0700445err_deep_sleep:
446 return VOS_STATUS_E_FAILURE;
447
448}
449
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530450/*
451 * Function: hdd_conf_hostoffload
452 * Central function to configure the supported offloads,
453 * either enable or disable them.
454 */
455void hdd_conf_hostoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
456{
457 hdd_context_t *pHddCtx = NULL;
458 v_CONTEXT_t *pVosContext = NULL;
459 VOS_STATUS vstatus = VOS_STATUS_E_FAILURE;
460
461 hddLog(VOS_TRACE_LEVEL_INFO, FL("Configuring offloads with flag: %d"),
462 fenable);
463
464 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
465
466 if (NULL == pVosContext)
467 {
468 hddLog(VOS_TRACE_LEVEL_ERROR, FL(" Global VOS context is Null"));
469 return;
470 }
471
472 //Get the HDD context.
473 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
474
475 if (NULL == pHddCtx)
476 {
477 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: HDD context is Null", __func__);
478 return;
479 }
480
481 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
482 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
483 {
484 if (fenable)
485 {
486 if (eConnectionState_Associated ==
487 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)
488 {
489 if ((pHddCtx->cfg_ini->fhostArpOffload))
490 {
491 /*
492 * Configure the ARP Offload.
493 * Even if it fails we have to reconfigure the MC/BC
494 * filter flag as we want RIVA not to drop BroadCast
495 * Packets
496 */
497 hddLog(VOS_TRACE_LEVEL_INFO,
498 FL("Calling ARP Offload with flag: %d"), fenable);
499 vstatus = hdd_conf_arp_offload(pAdapter, fenable);
500 pHddCtx->configuredMcastBcastFilter &=
501 ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST);
502
503 if (!VOS_IS_STATUS_SUCCESS(vstatus))
504 {
505 hddLog(VOS_TRACE_LEVEL_ERROR,
506 "Failed to enable ARPOFfloadFeature %d",
507 vstatus);
508 }
509 }
510 //Configure GTK_OFFLOAD
511#ifdef WLAN_FEATURE_GTK_OFFLOAD
512 hdd_conf_gtk_offload(pAdapter, fenable);
513#endif
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530514
515#ifdef WLAN_NS_OFFLOAD
516 if (pHddCtx->cfg_ini->fhostNSOffload)
517 {
518 /*
519 * Configure the NS Offload.
520 * Even if it fails we have to reconfigure the MC/BC filter flag
521 * as we want RIVA not to drop Multicast Packets
522 */
523
524 hddLog(VOS_TRACE_LEVEL_INFO,
525 FL("Calling NS Offload with flag: %d"), fenable);
526 hdd_conf_ns_offload(pAdapter, fenable);
527 pHddCtx->configuredMcastBcastFilter &=
528 ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST);
529 }
530#endif
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530531 }
532 }
533 else
534 {
535 //Disable ARPOFFLOAD
536 if (pHddCtx->cfg_ini->fhostArpOffload)
537 {
538 vstatus = hdd_conf_arp_offload(pAdapter, fenable);
539 if (!VOS_IS_STATUS_SUCCESS(vstatus))
540 {
541 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530542 "Failed to disable ARPOffload Feature %d", vstatus);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530543 }
544 }
545 //Disable GTK_OFFLOAD
546#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530547 hdd_conf_gtk_offload(pAdapter, fenable);
548#endif
549
550#ifdef WLAN_NS_OFFLOAD
551 //Disable NSOFFLOAD
552 if (pHddCtx->cfg_ini->fhostNSOffload)
553 {
554 hdd_conf_ns_offload(pAdapter, fenable);
555 }
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530556#endif
557 }
558 }
559 return;
560}
561
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530562#ifdef WLAN_NS_OFFLOAD
563void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
564{
565 struct inet6_dev *in6_dev;
566 struct inet6_ifaddr *ifp;
567 struct list_head *p;
568 tANI_U8 selfIPv6Addr[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA][SIR_MAC_IPV6_ADDR_LEN] = {{0,}};
569 tANI_BOOLEAN selfIPv6AddrValid[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA] = {0};
570 tSirHostOffloadReq offLoadRequest;
571
572 int i =0;
573 eHalStatus returnStatus;
574
575 ENTER();
576 if (fenable)
577 {
578 in6_dev = __in6_dev_get(pAdapter->dev);
579 if (NULL != in6_dev)
580 {
581 //read_lock_bh(&in6_dev->lock);
582 list_for_each(p, &in6_dev->addr_list)
583 {
584 ifp = list_entry(p, struct inet6_ifaddr, if_list);
585 switch(ipv6_addr_src_scope(&ifp->addr))
586 {
587 case IPV6_ADDR_SCOPE_LINKLOCAL:
588 vos_mem_copy(&selfIPv6Addr[0], &ifp->addr.s6_addr,
589 sizeof(ifp->addr.s6_addr));
590 selfIPv6AddrValid[0] = SIR_IPV6_ADDR_VALID;
591 break;
592 case IPV6_ADDR_SCOPE_GLOBAL:
593 vos_mem_copy(&selfIPv6Addr[1], &ifp->addr.s6_addr,
594 sizeof(ifp->addr.s6_addr));
595 selfIPv6AddrValid[1] = SIR_IPV6_ADDR_VALID;;
596 break;
597 default:
598 hddLog(LOGE, "The Scope %d is not supported",
599 ipv6_addr_src_scope(&ifp->addr));
600 }
601
602 }
603 //read_unlock_bh(&in6_dev->lock);
604 vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest));
605 for (i =0; i<SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA; i++)
606 {
607 if (selfIPv6AddrValid[i])
608 {
609 //Filling up the request structure
610 /* Filling the selfIPv6Addr with solicited address
611 * A Solicited-Node multicast address is created by
612 * taking the last 24 bits of a unicast or anycast
613 * address and appending them to the prefix
614 *
615 * FF02:0000:0000:0000:0000:0001:FFXX:XX
616 *
617 * here XX is the unicast/anycast bits
618 */
619 offLoadRequest.nsOffloadInfo.selfIPv6Addr[0] = 0xFF;
620 offLoadRequest.nsOffloadInfo.selfIPv6Addr[1] = 0x02;
621 offLoadRequest.nsOffloadInfo.selfIPv6Addr[11] = 0x01;
622 offLoadRequest.nsOffloadInfo.selfIPv6Addr[12] = 0xFF;
623 offLoadRequest.nsOffloadInfo.selfIPv6Addr[13] = selfIPv6Addr[i][13];
624 offLoadRequest.nsOffloadInfo.selfIPv6Addr[14] = selfIPv6Addr[i][14];
625 offLoadRequest.nsOffloadInfo.selfIPv6Addr[15] = selfIPv6Addr[i][15];
626 offLoadRequest.nsOffloadInfo.slotIdx = i;
627
628 vos_mem_copy(&offLoadRequest.nsOffloadInfo.targetIPv6Addr[0],
629 &selfIPv6Addr[i][0], sizeof(tANI_U8)*SIR_MAC_IPV6_ADDR_LEN);
630 vos_mem_copy(&offLoadRequest.nsOffloadInfo.selfMacAddr,
631 &pAdapter->macAddressCurrent.bytes,
632 sizeof(tANI_U8)*SIR_MAC_ADDR_LEN);
633
634 offLoadRequest.nsOffloadInfo.targetIPv6AddrValid[0] = SIR_IPV6_ADDR_VALID;
635 offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD;
636 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
637
638 vos_mem_copy(&offLoadRequest.params.hostIpv6Addr,
639 &offLoadRequest.nsOffloadInfo.targetIPv6Addr[0],
640 sizeof(tANI_U8)*SIR_MAC_IPV6_ADDR_LEN);
641
642 hddLog (VOS_TRACE_LEVEL_INFO,
643 "Setting NSOffload with solicitedIp: %pI6, targetIp: %pI6",
644 offLoadRequest.nsOffloadInfo.selfIPv6Addr,
645 offLoadRequest.nsOffloadInfo.targetIPv6Addr[0]);
646
647 //Configure the Firmware with this
648 returnStatus = sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
649 pAdapter->sessionId, &offLoadRequest);
650 if(eHAL_STATUS_SUCCESS != returnStatus)
651 {
652 hddLog(VOS_TRACE_LEVEL_ERROR,
653 FL("Failed to enable HostOffload feature with status: %d"),
654 returnStatus);
655 }
656 vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest));
657 }
658 }
659 }
660 else
661 {
662 hddLog(VOS_TRACE_LEVEL_ERROR,
663 FL("IPv6 dev does not exist. Failed to request NSOffload"));
664 return;
665 }
666 }
667 else
668 {
669 //Disable NSOffload
670 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
671 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
672 offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD;
673
674 if (eHAL_STATUS_SUCCESS !=
675 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
676 pAdapter->sessionId, &offLoadRequest))
677 {
678 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failure to disable"
679 "NSOffload feature"));
680 }
681 }
682 return;
683}
684#endif
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530685VOS_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
Jeff Johnson295189b2012-06-20 16:38:30 -0700686{
687 struct in_ifaddr **ifap = NULL;
688 struct in_ifaddr *ifa = NULL;
689 struct in_device *in_dev;
690 int i = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700691 tSirHostOffloadReq offLoadRequest;
Yathish9f22e662012-12-10 14:21:35 -0800692 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700693
694 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700695
Jeff Johnson295189b2012-06-20 16:38:30 -0700696 if(fenable)
697 {
698 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
699 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530700 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700701 ifap = &ifa->ifa_next)
702 {
703 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
704 {
705 break; /* found */
706 }
707 }
708 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700709 if(ifa && ifa->ifa_local)
710 {
711 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
712 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
713
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530714 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Enabled \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700715
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530716 if((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
717 pHddCtx->configuredMcastBcastFilter) ||
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700718 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530719 pHddCtx->configuredMcastBcastFilter))
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700720 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530721 offLoadRequest.enableOrDisable =
722 SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700723 }
724
725 //converting u32 to IPV4 address
726 for(i = 0 ; i < 4; i++)
727 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530728 offLoadRequest.params.hostIpv4Addr[i] =
Jeff Johnson295189b2012-06-20 16:38:30 -0700729 (ifa->ifa_local >> (i*8) ) & 0xFF ;
730 }
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530731 hddLog(VOS_TRACE_LEVEL_INFO, " Enable SME HostOffload: %d.%d.%d.%d",
Jeff Johnson295189b2012-06-20 16:38:30 -0700732 offLoadRequest.params.hostIpv4Addr[0],
733 offLoadRequest.params.hostIpv4Addr[1],
734 offLoadRequest.params.hostIpv4Addr[2],
735 offLoadRequest.params.hostIpv4Addr[3]);
736
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530737 if (eHAL_STATUS_SUCCESS !=
738 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
739 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700740 {
741 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to enable HostOffload "
742 "feature\n", __func__);
743 return VOS_STATUS_E_FAILURE;
744 }
745 return VOS_STATUS_SUCCESS;
746 }
747 else
748 {
749 hddLog(VOS_TRACE_LEVEL_INFO, "%s:IP Address is not assigned \n", __func__);
750 return VOS_STATUS_E_AGAIN;
751 }
752 }
753 else
754 {
755 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
756 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
757 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
758
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530759 if (eHAL_STATUS_SUCCESS !=
760 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
761 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700762 {
763 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to disable host "
764 "offload feature\n", __func__);
765 return VOS_STATUS_E_FAILURE;
766 }
767 return VOS_STATUS_SUCCESS;
768 }
769}
770
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530771/*
772 * This function is called before setting mcbc filters
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530773 * to modify filter value considering Different Offloads
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530774*/
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530775void hdd_mcbc_filter_modification(hdd_context_t* pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530776 tANI_U8 *pMcBcFilter)
777{
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530778 if (NULL == pHddCtx)
779 {
780 hddLog(VOS_TRACE_LEVEL_ERROR, FL("NULL HDD context passed"));
781 return;
782 }
783
784 *pMcBcFilter = pHddCtx->configuredMcastBcastFilter;
785 if (pHddCtx->cfg_ini->fhostArpOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530786 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530787 /* ARP offload is enabled, do not block bcast packets at RXP
788 * Will be using Bitmasking to reset the filter. As we have
789 * disable Broadcast filtering, Anding with the negation
790 * of Broadcast BIT
791 */
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530792 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530793 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530794
795#ifdef WLAN_NS_OFFLOAD
796 if (pHddCtx->cfg_ini->fhostNSOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530797 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530798 /* NS offload is enabled, do not block mcast packets at RXP
799 * Will be using Bitmasking to reset the filter. As we have
800 * disable Multicast filtering, Anding with the negation
801 * of Multicast BIT
802 */
803 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530804 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530805#endif
806
807 pHddCtx->configuredMcastBcastFilter = *pMcBcFilter;
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530808}
809
Jeff Johnson295189b2012-06-20 16:38:30 -0700810void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter)
811{
812 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700813 tpSirWlanSetRxpFilters wlanRxpFilterParam =
814 vos_mem_malloc(sizeof(tSirWlanSetRxpFilters));
815 if(NULL == wlanRxpFilterParam)
816 {
817 hddLog(VOS_TRACE_LEVEL_FATAL,
818 "%s: vos_mem_alloc failed ", __func__);
819 return;
820 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700821 hddLog(VOS_TRACE_LEVEL_INFO,
822 "%s: Configuring Mcast/Bcast Filter Setting. setfilter %d", __func__, setfilter);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530823 if (TRUE == setfilter)
824 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530825 hdd_mcbc_filter_modification(pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530826 &wlanRxpFilterParam->configuredMcstBcstFilterSetting);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530827 }
828 else
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530829 {
830 /*Use the current configured value to clear*/
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530831 wlanRxpFilterParam->configuredMcstBcstFilterSetting =
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530832 pHddCtx->configuredMcastBcastFilter;
833 }
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530834
Jeff Johnson295189b2012-06-20 16:38:30 -0700835 wlanRxpFilterParam->setMcstBcstFilter = setfilter;
Jeff Johnson295189b2012-06-20 16:38:30 -0700836 halStatus = sme_ConfigureRxpFilter(pHddCtx->hHal, wlanRxpFilterParam);
Chilam Ngc4244af2013-04-01 15:37:32 -0700837 if (eHAL_STATUS_SUCCESS != halStatus)
838 vos_mem_free(wlanRxpFilterParam);
Jeff Johnson295189b2012-06-20 16:38:30 -0700839 if(setfilter && (eHAL_STATUS_SUCCESS == halStatus))
840 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
841}
842
Jeff Johnson295189b2012-06-20 16:38:30 -0700843static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx,
844 hdd_adapter_t *pAdapter)
845{
846 eHalStatus halStatus = eHAL_STATUS_FAILURE;
847 tpSirWlanSuspendParam wlanSuspendParam =
848 vos_mem_malloc(sizeof(tSirWlanSuspendParam));
849
850 if(NULL == wlanSuspendParam)
851 {
852 hddLog(VOS_TRACE_LEVEL_FATAL,
853 "%s: vos_mem_alloc failed ", __func__);
854 return;
855 }
856
857 hddLog(VOS_TRACE_LEVEL_INFO,
858 "%s: send wlan suspend indication", __func__);
859
860 if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER))
861 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530862 //Configure supported OffLoads
863 hdd_conf_hostoffload(pAdapter, TRUE);
864 wlanSuspendParam->configuredMcstBcstFilterSetting = pHddCtx->configuredMcastBcastFilter;
Jeff Johnson295189b2012-06-20 16:38:30 -0700865
866#ifdef WLAN_FEATURE_PACKET_FILTERING
867 if (pHddCtx->cfg_ini->isMcAddrListFilter)
868 {
869 /*Multicast addr list filter is enabled during suspend*/
870 if (((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
871 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT))
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530872 && pAdapter->mc_addr_list.mc_cnt
Jeff Johnson295189b2012-06-20 16:38:30 -0700873 && (eConnectionState_Associated ==
874 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
875 {
876 /*set the filter*/
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530877 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700878 }
879 }
880#endif
881 }
882
883 halStatus = sme_ConfigureSuspendInd(pHddCtx->hHal, wlanSuspendParam);
884 if(eHAL_STATUS_SUCCESS == halStatus)
885 {
886 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
Chilam Ngc4244af2013-04-01 15:37:32 -0700887 } else {
888 vos_mem_free(wlanSuspendParam);
Jeff Johnson295189b2012-06-20 16:38:30 -0700889 }
890}
891
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530892static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700893{
Chilam Ngc4244af2013-04-01 15:37:32 -0700894 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Yathish9f22e662012-12-10 14:21:35 -0800895 hdd_context_t* pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Chilam Ngc4244af2013-04-01 15:37:32 -0700896 tpSirWlanResumeParam wlanResumeParam;
Jeff Johnson295189b2012-06-20 16:38:30 -0700897
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530898 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700899 "%s: send wlan resume indication", __func__);
900
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530901 if (pHddCtx->hdd_mcastbcast_filter_set == TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -0700902 {
Chilam Ngc4244af2013-04-01 15:37:32 -0700903 wlanResumeParam = vos_mem_malloc(sizeof(tSirWlanResumeParam));
904
905 if(NULL == wlanResumeParam)
906 {
907 hddLog(VOS_TRACE_LEVEL_FATAL,
908 "%s: vos_mem_alloc failed ", __func__);
909 return;
910 }
911
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530912 //Disable supported OffLoads
913 hdd_conf_hostoffload(pAdapter, FALSE);
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530914
915 wlanResumeParam->configuredMcstBcstFilterSetting =
916 pHddCtx->configuredMcastBcastFilter;
Chilam Ngc4244af2013-04-01 15:37:32 -0700917 halStatus = sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam);
918 if (eHAL_STATUS_SUCCESS != halStatus)
919 vos_mem_free(wlanResumeParam);
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530920 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700921 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700922
Chilam Ngc4244af2013-04-01 15:37:32 -0700923
Jeff Johnson295189b2012-06-20 16:38:30 -0700924#ifdef WLAN_FEATURE_PACKET_FILTERING
925 if (pHddCtx->cfg_ini->isMcAddrListFilter)
926 {
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530927 /*Multicast addr filtering is enabled*/
928 if (pAdapter->mc_addr_list.isFilterApplied)
Jeff Johnson295189b2012-06-20 16:38:30 -0700929 {
930 /*Filter applied during suspend mode*/
931 /*Clear it here*/
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530932 wlan_hdd_set_mc_addr_list(pAdapter, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700933 }
934 }
935#endif
936}
Jeff Johnson295189b2012-06-20 16:38:30 -0700937
Jeff Johnson295189b2012-06-20 16:38:30 -0700938//Suspend routine registered with Android OS
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800939void hdd_suspend_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -0700940{
941 hdd_context_t *pHddCtx = NULL;
942 v_CONTEXT_t pVosContext = NULL;
943
Jeff Johnson295189b2012-06-20 16:38:30 -0700944 VOS_STATUS status;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +0530945 hdd_adapter_t *pAdapter = NULL;
946 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Jeff Johnsonbc676b42013-02-14 16:04:08 -0800947
Jeff Johnson295189b2012-06-20 16:38:30 -0700948 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__);
949
950 //Get the global VOSS context.
951 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
952 if(!pVosContext) {
953 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
954 return;
955 }
956
957 //Get the HDD context.
958 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
959
960 if(!pHddCtx) {
961 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
962 return;
963 }
964
965 if (pHddCtx->isLogpInProgress) {
966 hddLog(VOS_TRACE_LEVEL_ERROR,
967 "%s: Ignore suspend wlan, LOGP in progress!", __func__);
968 return;
969 }
970
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +0530971 hdd_set_pwrparams(pHddCtx);
972
973 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
974 {
975 /* put the device into full power */
976 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
977
978 /* put the device back into BMPS */
979 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
980
981 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
982 }
983
Jeff Johnson295189b2012-06-20 16:38:30 -0700984 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
985 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
986 {
987 pAdapter = pAdapterNode->pAdapter;
988 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -0700989 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -0700990 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
991
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -0700992 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -0700993 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
994 pAdapterNode = pNext;
995 continue;
996 }
997
998#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
999 if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1000 {
1001 //stop the interface before putting the chip to standby
1002 netif_tx_disable(pAdapter->dev);
1003 netif_carrier_off(pAdapter->dev);
1004 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301005 else if (pHddCtx->cfg_ini->nEnableSuspend ==
Jeff Johnson295189b2012-06-20 16:38:30 -07001006 WLAN_MAP_SUSPEND_TO_DEEP_SLEEP)
1007 {
1008 //Execute deep sleep procedure
1009 hdd_enter_deep_sleep(pHddCtx, pAdapter);
1010 }
1011#endif
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301012
1013 /*Suspend notification sent down to driver*/
1014 hdd_conf_suspend_ind(pHddCtx, pAdapter);
1015
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301016 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1017 pAdapterNode = pNext;
1018 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301019 pHddCtx->hdd_wlan_suspended = TRUE;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301020
Jeff Johnson295189b2012-06-20 16:38:30 -07001021#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1022 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1023 {
1024 hdd_enter_standby(pHddCtx);
1025 }
1026#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001027
1028 return;
1029}
1030
1031static void hdd_PowerStateChangedCB
1032(
1033 v_PVOID_t callbackContext,
1034 tPmcState newState
1035)
1036{
1037 hdd_context_t *pHddCtx = callbackContext;
1038
1039 /* if the driver was not in BMPS during early suspend,
1040 * the dynamic DTIM is now updated at Riva */
1041 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended
1042 && pHddCtx->cfg_ini->enableDynamicDTIM
1043 && (pHddCtx->hdd_ignore_dtim_enabled == FALSE))
1044 {
1045 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1046 }
1047 spin_lock(&pHddCtx->filter_lock);
Gopichand Nakkalac1b11522013-03-25 15:25:33 +05301048 if((newState == BMPS) && pHddCtx->hdd_wlan_suspended) {
Jeff Johnson295189b2012-06-20 16:38:30 -07001049 spin_unlock(&pHddCtx->filter_lock);
1050 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001051 if(pHddCtx->hdd_mcastbcast_filter_set != TRUE)
1052 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__);
1053 }
1054 else
1055 spin_unlock(&pHddCtx->filter_lock);
1056}
1057
1058
1059
1060void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx)
1061{
1062 v_CONTEXT_t pVosContext;
1063 tHalHandle smeContext;
1064
1065 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1066 if (NULL == pVosContext)
1067 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001068 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001069 return;
1070 }
1071 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1072 if (NULL == smeContext)
1073 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001074 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001075 return;
1076 }
1077
1078 spin_lock_init(&pHddCtx->filter_lock);
1079 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1080 pHddCtx->cfg_ini->nEnableSuspend)
1081 {
1082 pmcRegisterDeviceStateUpdateInd(smeContext,
1083 hdd_PowerStateChangedCB, pHddCtx);
1084 }
1085}
1086
1087void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx)
1088{
1089 v_CONTEXT_t pVosContext;
1090 tHalHandle smeContext;
1091
1092 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1093 if (NULL == pVosContext)
1094 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001095 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001096 return;
1097 }
1098 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1099 if (NULL == smeContext)
1100 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001101 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001102 return;
1103 }
1104
1105 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1106 pHddCtx->cfg_ini->nEnableSuspend)
1107 {
1108 pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB);
1109 }
1110}
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301111
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301112#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301113void hdd_conf_gtk_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301114{
1115 eHalStatus ret;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301116 tSirGtkOffloadParams hddGtkOffloadReqParams;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301117 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1118
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301119 if(fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301120 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301121 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1122 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags ))
1123 {
1124 vos_mem_copy(&hddGtkOffloadReqParams,
1125 &pHddStaCtx->gtkOffloadReqParams,
1126 sizeof (tSirGtkOffloadParams));
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301127
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301128 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1129 &hddGtkOffloadReqParams, pAdapter->sessionId);
1130 if (eHAL_STATUS_SUCCESS != ret)
1131 {
1132 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1133 "%s: sme_SetGTKOffload failed, returned %d",
1134 __func__, ret);
1135 return;
1136 }
1137
1138 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1139 "%s: sme_SetGTKOffload successfull", __func__);
1140 }
1141
1142 }
1143 else
1144 {
1145 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1146 (0 == memcmp(&pHddStaCtx->gtkOffloadReqParams.bssId,
1147 &pHddStaCtx->conn_info.bssId, WNI_CFG_BSSID_LEN)) &&
1148 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags))
1149 {
1150
1151 /* Host driver has previously offloaded GTK rekey */
1152 ret = sme_GetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301153 wlan_hdd_cfg80211_update_replayCounterCallback,
1154 pAdapter, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301155 if (eHAL_STATUS_SUCCESS != ret)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301156
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301157 {
1158 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1159 "%s: sme_GetGTKOffload failed, returned %d",
1160 __func__, ret);
1161 return;
1162 }
1163 else
1164 {
1165 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1166 "%s: sme_GetGTKOffload successful",
1167 __func__);
1168
1169 /* Sending GTK offload dissable */
1170 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
1171 sizeof (tSirGtkOffloadParams));
1172 hddGtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE;
1173 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301174 &hddGtkOffloadReqParams, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301175 if (eHAL_STATUS_SUCCESS != ret)
1176 {
1177 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1178 "%s: failed to dissable GTK offload, returned %d",
1179 __func__, ret);
1180 return;
1181 }
1182 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1183 "%s: successfully dissabled GTK offload request to HAL",
1184 __func__);
1185 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301186 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301187 }
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301188 return;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301189}
1190#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
Jeff Johnson295189b2012-06-20 16:38:30 -07001191
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001192void hdd_resume_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001193{
1194 hdd_context_t *pHddCtx = NULL;
1195 hdd_adapter_t *pAdapter = NULL;
1196 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1197 VOS_STATUS status;
1198 v_CONTEXT_t pVosContext = NULL;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001199
Jeff Johnson295189b2012-06-20 16:38:30 -07001200 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
1201
1202 //Get the global VOSS context.
1203 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1204 if(!pVosContext) {
1205 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1206 return;
1207 }
1208
1209 //Get the HDD context.
1210 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1211
1212 if(!pHddCtx) {
1213 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1214 return;
1215 }
1216
1217 if (pHddCtx->isLogpInProgress) {
1218 hddLog(VOS_TRACE_LEVEL_INFO,
1219 "%s: Ignore resume wlan, LOGP in progress!", __func__);
1220 return;
1221 }
1222
Jeff Johnson295189b2012-06-20 16:38:30 -07001223 pHddCtx->hdd_wlan_suspended = FALSE;
1224 /*loop through all adapters. Concurrency */
1225 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1226
1227 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1228 {
1229 pAdapter = pAdapterNode->pAdapter;
1230 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001231 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001232 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001233 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001234 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1235 pAdapterNode = pNext;
1236 continue;
1237 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301238
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301239
Jeff Johnson295189b2012-06-20 16:38:30 -07001240#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1241 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP)
1242 {
1243 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__);
1244 hdd_exit_deep_sleep(pAdapter);
1245 }
1246#endif
1247
1248 if(pHddCtx->hdd_ignore_dtim_enabled == TRUE)
1249 {
1250 /*Switch back to DTIM 1*/
1251 tSirSetPowerParamsReq powerRequest = { 0 };
1252
1253 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
1254 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07001255 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001256
1257 /*Disabled ModulatedDTIM if enabled on suspend*/
1258 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1259 powerRequest.uDTIMPeriod = 0;
1260
1261 /* Update ignoreDTIM and ListedInterval in CFG with default values */
1262 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1263 NULL, eANI_BOOLEAN_FALSE);
1264 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1265 NULL, eANI_BOOLEAN_FALSE);
1266
1267 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1268 "Switch to DTIM%d \n",powerRequest.uListenInterval);
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08001269 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001270
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301271 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
1272 {
1273 /* put the device into full power */
1274 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001275
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301276 /* put the device back into BMPS */
1277 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
Jeff Johnson295189b2012-06-20 16:38:30 -07001278
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301279 pHddCtx->hdd_ignore_dtim_enabled = FALSE;
1280 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001281 }
1282
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301283 hdd_conf_resume_ind(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001284 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1285 pAdapterNode = pNext;
1286 }
1287
1288#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1289 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY)
1290 {
1291 hdd_exit_standby(pHddCtx);
1292 }
1293#endif
1294
Jeff Johnson295189b2012-06-20 16:38:30 -07001295 return;
1296}
1297
Jeff Johnson295189b2012-06-20 16:38:30 -07001298VOS_STATUS hdd_wlan_reset_initialization(void)
1299{
Jeff Johnson295189b2012-06-20 16:38:30 -07001300 v_CONTEXT_t pVosContext = NULL;
1301
1302 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1303
1304 //Get the global VOSS context.
1305 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1306 if(!pVosContext)
1307 {
1308 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1309 return VOS_STATUS_E_FAILURE;
1310 }
1311
1312 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__);
1313
1314 // Prevent the phone from going to sleep
1315 hdd_prevent_suspend();
1316
Jeff Johnson295189b2012-06-20 16:38:30 -07001317 return VOS_STATUS_SUCCESS;
1318}
1319
1320
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001321/*
1322 * Based on the ioctl command recieved by HDD, put WLAN driver
1323 * into the quiet mode. This is the same as the early suspend
1324 * notification that driver used to listen
1325 */
1326void hdd_set_wlan_suspend_mode(bool suspend)
Jeff Johnson295189b2012-06-20 16:38:30 -07001327{
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001328 if (suspend)
1329 hdd_suspend_wlan();
1330 else
1331 hdd_resume_wlan();
Jeff Johnson295189b2012-06-20 16:38:30 -07001332}
1333
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001334static void hdd_ssr_timer_init(void)
1335{
1336 init_timer(&ssr_timer);
1337}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001338
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001339static void hdd_ssr_timer_del(void)
1340{
1341 del_timer(&ssr_timer);
1342 ssr_timer_started = false;
1343}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001344
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001345static void hdd_ssr_timer_cb(unsigned long data)
1346{
1347 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD SSR timer expired", __func__);
1348 VOS_BUG(0);
1349}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001350
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001351static void hdd_ssr_timer_start(int msec)
1352{
1353 if(ssr_timer_started)
1354 {
1355 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: trying to start SSR timer when it's running"
1356 ,__func__);
1357 }
1358 ssr_timer.expires = jiffies + msecs_to_jiffies(msec);
1359 ssr_timer.function = hdd_ssr_timer_cb;
1360 add_timer(&ssr_timer);
1361 ssr_timer_started = true;
1362}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001363
Jeff Johnson295189b2012-06-20 16:38:30 -07001364/* the HDD interface to WLAN driver shutdown,
1365 * the primary shutdown function in SSR
1366 */
1367VOS_STATUS hdd_wlan_shutdown(void)
1368{
1369 VOS_STATUS vosStatus;
1370 v_CONTEXT_t pVosContext = NULL;
1371 hdd_context_t *pHddCtx = NULL;
1372 pVosSchedContext vosSchedContext = NULL;
1373
1374 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__);
1375
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001376 /* if re-init never happens, then do SSR1 */
1377 hdd_ssr_timer_init();
1378 hdd_ssr_timer_start(HDD_SSR_BRING_UP_TIME);
1379
Jeff Johnson295189b2012-06-20 16:38:30 -07001380 /* Get the global VOSS context. */
1381 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1382 if(!pVosContext) {
1383 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1384 return VOS_STATUS_E_FAILURE;
1385 }
1386 /* Get the HDD context. */
1387 pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1388 if(!pHddCtx) {
1389 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1390 return VOS_STATUS_E_FAILURE;
1391 }
1392 hdd_reset_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001393 /* DeRegister with platform driver as client for Suspend/Resume */
1394 vosStatus = hddDeregisterPmOps(pHddCtx);
1395 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1396 {
1397 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
1398 }
1399
1400 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
1401 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1402 {
1403 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
1404 }
1405
1406 /* Disable IMPS/BMPS as we do not want the device to enter any power
1407 * save mode on its own during reset sequence
1408 */
1409 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1410 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1411 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1412
1413 vosSchedContext = get_vos_sched_ctxt();
1414
1415 /* Wakeup all driver threads */
1416 if(TRUE == pHddCtx->isMcThreadSuspended){
1417 complete(&vosSchedContext->ResumeMcEvent);
1418 pHddCtx->isMcThreadSuspended= FALSE;
1419 }
1420 if(TRUE == pHddCtx->isTxThreadSuspended){
1421 complete(&vosSchedContext->ResumeTxEvent);
1422 pHddCtx->isTxThreadSuspended= FALSE;
1423 }
1424 if(TRUE == pHddCtx->isRxThreadSuspended){
1425 complete(&vosSchedContext->ResumeRxEvent);
1426 pHddCtx->isRxThreadSuspended= FALSE;
1427 }
1428 /* Reset the Suspend Variable */
1429 pHddCtx->isWlanSuspended = FALSE;
1430
1431 /* Stop all the threads; we do not want any messages to be a processed,
1432 * any more and the best way to ensure that is to terminate the threads
1433 * gracefully.
1434 */
1435 /* Wait for MC to exit */
1436 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
1437 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
1438 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
1439 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
1440 wait_for_completion_interruptible(&vosSchedContext->McShutdown);
1441
1442 /* Wait for TX to exit */
1443 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
1444 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
1445 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
1446 wake_up_interruptible(&vosSchedContext->txWaitQueue);
1447 wait_for_completion_interruptible(&vosSchedContext->TxShutdown);
1448
1449 /* Wait for RX to exit */
1450 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
1451 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
1452 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
1453 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
1454 wait_for_completion_interruptible(&vosSchedContext->RxShutdown);
1455
1456#ifdef WLAN_BTAMP_FEATURE
1457 vosStatus = WLANBAP_Stop(pVosContext);
1458 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1459 {
1460 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1461 "%s: Failed to stop BAP",__func__);
1462 }
1463#endif //WLAN_BTAMP_FEATURE
1464 vosStatus = vos_wda_shutdown(pVosContext);
1465 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1466
1467 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
1468 /* Stop SME - Cannot invoke vos_stop as vos_stop relies
1469 * on threads being running to process the SYS Stop
1470 */
1471 vosStatus = sme_Stop(pHddCtx->hHal, TRUE);
1472 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1473
1474 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
1475 /* Stop MAC (PE and HAL) */
1476 vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
1477 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1478
1479 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
1480 /* Stop TL */
1481 vosStatus = WLANTL_Stop(pVosContext);
1482 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1483
Jeff Johnson295189b2012-06-20 16:38:30 -07001484 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001485 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__);
1486 /* Clean up message queues of TX and MC thread */
1487 vos_sched_flush_mc_mqs(vosSchedContext);
1488 vos_sched_flush_tx_mqs(vosSchedContext);
1489 vos_sched_flush_rx_mqs(vosSchedContext);
1490
1491 /* Deinit all the TX and MC queues */
1492 vos_sched_deinit_mqs(vosSchedContext);
1493 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__);
1494
1495 /* shutdown VOSS */
1496 vos_shutdown(pVosContext);
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05301497
1498 /*mac context has already been released in mac_close call
1499 so setting it to NULL in hdd context*/
1500 pHddCtx->hHal = (tHalHandle)NULL;
1501
Jeff Johnson295189b2012-06-20 16:38:30 -07001502 if (free_riva_power_on_lock("wlan"))
1503 {
1504 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
1505 __func__);
1506 }
1507 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete"
1508 ,__func__);
1509 return VOS_STATUS_SUCCESS;
1510}
1511
1512
1513
1514/* the HDD interface to WLAN driver re-init.
1515 * This is called to initialize/start WLAN driver after a shutdown.
1516 */
1517VOS_STATUS hdd_wlan_re_init(void)
1518{
1519 VOS_STATUS vosStatus;
1520 v_CONTEXT_t pVosContext = NULL;
1521 hdd_context_t *pHddCtx = NULL;
1522 eHalStatus halStatus;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07001523#ifdef HAVE_WCNSS_CAL_DOWNLOAD
1524 int max_retries = 0;
1525#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001526#ifdef WLAN_BTAMP_FEATURE
1527 hdd_config_t *pConfig = NULL;
1528 WLANBAP_ConfigType btAmpConfig;
1529#endif
1530
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001531 hdd_ssr_timer_del();
Jeff Johnson295189b2012-06-20 16:38:30 -07001532 hdd_prevent_suspend();
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001533
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07001534#ifdef HAVE_WCNSS_CAL_DOWNLOAD
1535 /* wait until WCNSS driver downloads NV */
1536 while (!wcnss_device_ready() && 5 >= ++max_retries) {
1537 msleep(1000);
1538 }
1539 if (max_retries >= 5) {
1540 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
1541 goto err_re_init;
1542 }
1543#endif
1544
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001545 /* The driver should always be initialized in STA mode after SSR */
1546 hdd_set_conparam(0);
1547
Jeff Johnson295189b2012-06-20 16:38:30 -07001548 /* Re-open VOSS, it is a re-open b'se control transport was never closed. */
1549 vosStatus = vos_open(&pVosContext, 0);
1550 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1551 {
1552 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
1553 goto err_re_init;
1554 }
1555
1556 /* Get the HDD context. */
1557 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1558 if(!pHddCtx)
1559 {
1560 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1561 goto err_vosclose;
1562 }
1563
1564 /* Save the hal context in Adapter */
1565 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
1566 if ( NULL == pHddCtx->hHal )
1567 {
1568 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
1569 goto err_vosclose;
1570 }
1571
1572 /* Set the SME configuration parameters. */
1573 vosStatus = hdd_set_sme_config(pHddCtx);
1574 if ( VOS_STATUS_SUCCESS != vosStatus )
1575 {
1576 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
1577 goto err_vosclose;
1578 }
1579
1580 /* Initialize the WMM module */
1581 vosStatus = hdd_wmm_init(pHddCtx);
1582 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
1583 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001584 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001585 goto err_vosclose;
1586 }
1587
1588 vosStatus = vos_preStart( pHddCtx->pvosContext );
1589 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1590 {
1591 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
1592 goto err_vosclose;
1593 }
1594
1595 /* In the integrated architecture we update the configuration from
1596 the INI file and from NV before vOSS has been started so that
1597 the final contents are available to send down to the cCPU */
1598 /* Apply the cfg.ini to cfg.dat */
1599 if (FALSE == hdd_update_config_dat(pHddCtx))
1600 {
1601 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
1602 goto err_vosclose;
1603 }
1604
1605 /* Set the MAC Address, currently this is used by HAL to add self sta.
1606 * Remove this once self sta is added as part of session open. */
1607 halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID,
1608 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
1609 sizeof(pHddCtx->cfg_ini->intfMacAddr[0]));
1610 if (!HAL_STATUS_SUCCESS(halStatus))
1611 {
1612 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
1613 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus);
1614 goto err_vosclose;
1615 }
1616
1617 /* Start VOSS which starts up the SME/MAC/HAL modules and everything else
1618 Note: Firmware image will be read and downloaded inside vos_start API */
1619 vosStatus = vos_start( pVosContext );
1620 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1621 {
1622 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
1623 goto err_vosclose;
1624 }
1625
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07001626 /* Exchange capability info between Host and FW and also get versioning info from FW */
1627 hdd_exchange_version_and_caps(pHddCtx);
1628
Jeff Johnson295189b2012-06-20 16:38:30 -07001629 vosStatus = hdd_post_voss_start_config( pHddCtx );
1630 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1631 {
1632 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
1633 __func__);
1634 goto err_vosstop;
1635 }
1636
1637#ifdef WLAN_BTAMP_FEATURE
1638 vosStatus = WLANBAP_Open(pVosContext);
1639 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1640 {
1641 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1642 "%s: Failed to open BAP",__func__);
1643 goto err_vosstop;
1644 }
1645 vosStatus = BSL_Init(pVosContext);
1646 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1647 {
1648 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1649 "%s: Failed to Init BSL",__func__);
1650 goto err_bap_close;
1651 }
1652 vosStatus = WLANBAP_Start(pVosContext);
1653 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1654 {
1655 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1656 "%s: Failed to start TL",__func__);
1657 goto err_bap_close;
1658 }
1659 pConfig = pHddCtx->cfg_ini;
1660 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
1661 vosStatus = WLANBAP_SetConfig(&btAmpConfig);
1662#endif //WLAN_BTAMP_FEATURE
1663
1664 /* Restart all adapters */
1665 hdd_start_all_adapters(pHddCtx);
1666 pHddCtx->isLogpInProgress = FALSE;
1667 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001668 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001669
1670 /* Register with platform driver as client for Suspend/Resume */
1671 vosStatus = hddRegisterPmOps(pHddCtx);
1672 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1673 {
1674 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
1675 goto err_bap_stop;
1676 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001677 /* Allow the phone to go to sleep */
1678 hdd_allow_suspend();
1679 /* register for riva power on lock */
1680 if (req_riva_power_on_lock("wlan"))
1681 {
1682 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
1683 __func__);
1684 goto err_unregister_pmops;
1685 }
1686 goto success;
1687
1688err_unregister_pmops:
1689 hddDeregisterPmOps(pHddCtx);
1690
1691err_bap_stop:
Jeff Johnson32d95a32012-09-10 13:15:23 -07001692#ifdef CONFIG_HAS_EARLYSUSPEND
1693 hdd_unregister_mcast_bcast_filter(pHddCtx);
1694#endif
1695 hdd_close_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001696#ifdef WLAN_BTAMP_FEATURE
Jeff Johnson32d95a32012-09-10 13:15:23 -07001697 WLANBAP_Stop(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07001698#endif
1699
1700#ifdef WLAN_BTAMP_FEATURE
1701err_bap_close:
1702 WLANBAP_Close(pVosContext);
1703#endif
1704
1705err_vosstop:
1706 vos_stop(pVosContext);
1707
1708err_vosclose:
1709 vos_close(pVosContext);
1710 vos_sched_close(pVosContext);
1711 if (pHddCtx)
1712 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001713 /* Unregister the Net Device Notifier */
1714 unregister_netdevice_notifier(&hdd_netdev_notifier);
1715 /* Clean up HDD Nlink Service */
1716 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1717 nl_srv_exit();
Jeff Johnson295189b2012-06-20 16:38:30 -07001718 /* Free up dynamically allocated members inside HDD Adapter */
1719 kfree(pHddCtx->cfg_ini);
1720 pHddCtx->cfg_ini= NULL;
1721
Jeff Johnson295189b2012-06-20 16:38:30 -07001722 wiphy_unregister(pHddCtx->wiphy);
1723 wiphy_free(pHddCtx->wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07001724 }
1725 vos_preClose(&pVosContext);
1726
1727#ifdef MEMORY_DEBUG
1728 vos_mem_exit();
1729#endif
1730
1731err_re_init:
1732 /* Allow the phone to go to sleep */
1733 hdd_allow_suspend();
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001734 return -EPERM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001735
1736success:
1737 /* Trigger replay of BTC events */
1738 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1739 return VOS_STATUS_SUCCESS;
1740}