blob: a815c8f91ce3a18c88ea88707195f700eb58d50d [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
Sameer Thalappile5637f42013-08-07 15:46:55 -0700109#define HDD_SSR_BRING_UP_TIME 180000
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 {
Jeff Johnson0299d0a2013-10-30 12:37:43 -0700431 hddLog(VOS_TRACE_LEVEL_FATAL,"sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -0700432 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
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530564void hdd_ipv6_notifier_work_queue(struct work_struct *work)
565{
566 hdd_adapter_t* pAdapter =
567 container_of(work, hdd_adapter_t, ipv6NotifierWorkQueue);
568 hdd_context_t *pHddCtx;
569 int status;
570
571 hddLog(LOG1, FL("Reconfiguring NS Offload"));
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530572
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530573 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
574 status = wlan_hdd_validate_context(pHddCtx);
575 if (0 != status)
576 {
577 hddLog(LOGE, FL("HDD context is invalid"));
578 return;
579 }
580
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530581 if ((eConnectionState_Associated ==
582 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)
583 && (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid))
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530584 {
585 // This invocation being part of the IPv6 registration callback,
586 // we are passing second parameter as 2 to avoid registration
587 // of IPv6 notifier again.
588 hdd_conf_ns_offload(pAdapter, 2);
589 }
590}
591
592static int wlan_hdd_ipv6_changed(struct notifier_block *nb,
593 unsigned long data, void *arg)
594{
595 struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)arg;
596 struct net_device *ndev = ifa->idev->dev;
597 hdd_adapter_t *pAdapter =
598 container_of(nb, struct hdd_adapter_s, ipv6_notifier);
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530599 hdd_context_t *pHddCtx;
600 int status;
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530601
602 if (pAdapter && pAdapter->dev == ndev)
603 {
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530604 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
605 status = wlan_hdd_validate_context(pHddCtx);
606 if (0 != status)
607 {
608 hddLog(LOGE, FL("HDD context is invalid"));
609 return NOTIFY_DONE;
610 }
611
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530612 schedule_work(&pAdapter->ipv6NotifierWorkQueue);
613 }
614
615 return NOTIFY_DONE;
616}
617
618/**----------------------------------------------------------------------------
619
620 \brief hdd_conf_ns_offload() - Configure NS offload
621
622 Called during SUSPEND to configure the NS offload (MC BC filter) which
623 reduces power consumption.
624
625 \param - pAdapter - Adapter context for which NS offload is to be configured
626 \param - fenable - 0 - disable.
627 1 - enable. (with IPv6 notifier registration)
628 2 - enable. (without IPv6 notifier registration)
629
630 \return - void
631
632 ---------------------------------------------------------------------------*/
633void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, int fenable)
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530634{
635 struct inet6_dev *in6_dev;
636 struct inet6_ifaddr *ifp;
637 struct list_head *p;
638 tANI_U8 selfIPv6Addr[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA][SIR_MAC_IPV6_ADDR_LEN] = {{0,}};
639 tANI_BOOLEAN selfIPv6AddrValid[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA] = {0};
640 tSirHostOffloadReq offLoadRequest;
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530641 hdd_context_t *pHddCtx;
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530642
643 int i =0;
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530644 int ret =0;
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530645 eHalStatus returnStatus;
646
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530647 ENTER();
648 hddLog(LOG1, FL(" fenable = %d"), fenable);
649
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530650 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
651
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530652 if (fenable)
653 {
654 in6_dev = __in6_dev_get(pAdapter->dev);
655 if (NULL != in6_dev)
656 {
657 //read_lock_bh(&in6_dev->lock);
658 list_for_each(p, &in6_dev->addr_list)
659 {
660 ifp = list_entry(p, struct inet6_ifaddr, if_list);
661 switch(ipv6_addr_src_scope(&ifp->addr))
662 {
663 case IPV6_ADDR_SCOPE_LINKLOCAL:
664 vos_mem_copy(&selfIPv6Addr[0], &ifp->addr.s6_addr,
665 sizeof(ifp->addr.s6_addr));
666 selfIPv6AddrValid[0] = SIR_IPV6_ADDR_VALID;
Hardik Kantilal Patel1341bdf2013-08-22 20:27:15 +0530667 hddLog (VOS_TRACE_LEVEL_INFO,
668 "Found IPV6_ADDR_SCOPE_LINKLOCAL Address : %pI6",
669 selfIPv6Addr[0]);
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530670 break;
671 case IPV6_ADDR_SCOPE_GLOBAL:
672 vos_mem_copy(&selfIPv6Addr[1], &ifp->addr.s6_addr,
673 sizeof(ifp->addr.s6_addr));
Hardik Kantilal Patel1341bdf2013-08-22 20:27:15 +0530674 selfIPv6AddrValid[1] = SIR_IPV6_ADDR_VALID;
675 hddLog (VOS_TRACE_LEVEL_INFO,
676 "Found IPV6_ADDR_SCOPE_GLOBAL Address : %pI6",
677 selfIPv6Addr[1]);
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530678 break;
679 default:
680 hddLog(LOGE, "The Scope %d is not supported",
681 ipv6_addr_src_scope(&ifp->addr));
682 }
683
684 }
685 //read_unlock_bh(&in6_dev->lock);
686 vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest));
687 for (i =0; i<SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA; i++)
688 {
689 if (selfIPv6AddrValid[i])
690 {
691 //Filling up the request structure
692 /* Filling the selfIPv6Addr with solicited address
693 * A Solicited-Node multicast address is created by
694 * taking the last 24 bits of a unicast or anycast
695 * address and appending them to the prefix
696 *
697 * FF02:0000:0000:0000:0000:0001:FFXX:XX
698 *
699 * here XX is the unicast/anycast bits
700 */
701 offLoadRequest.nsOffloadInfo.selfIPv6Addr[0] = 0xFF;
702 offLoadRequest.nsOffloadInfo.selfIPv6Addr[1] = 0x02;
703 offLoadRequest.nsOffloadInfo.selfIPv6Addr[11] = 0x01;
704 offLoadRequest.nsOffloadInfo.selfIPv6Addr[12] = 0xFF;
705 offLoadRequest.nsOffloadInfo.selfIPv6Addr[13] = selfIPv6Addr[i][13];
706 offLoadRequest.nsOffloadInfo.selfIPv6Addr[14] = selfIPv6Addr[i][14];
707 offLoadRequest.nsOffloadInfo.selfIPv6Addr[15] = selfIPv6Addr[i][15];
708 offLoadRequest.nsOffloadInfo.slotIdx = i;
709
710 vos_mem_copy(&offLoadRequest.nsOffloadInfo.targetIPv6Addr[0],
711 &selfIPv6Addr[i][0], sizeof(tANI_U8)*SIR_MAC_IPV6_ADDR_LEN);
712 vos_mem_copy(&offLoadRequest.nsOffloadInfo.selfMacAddr,
713 &pAdapter->macAddressCurrent.bytes,
714 sizeof(tANI_U8)*SIR_MAC_ADDR_LEN);
715
716 offLoadRequest.nsOffloadInfo.targetIPv6AddrValid[0] = SIR_IPV6_ADDR_VALID;
717 offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD;
718 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
719
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530720 hddLog (VOS_TRACE_LEVEL_INFO,
721 "configuredMcastBcastFilter: %d",pHddCtx->configuredMcastBcastFilter);
722
Kiet Lamc8e1eb52013-10-24 00:30:49 +0530723 if ((VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid)
724 && ((HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST ==
725 pHddCtx->sus_res_mcastbcast_filter) ||
726 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
727 pHddCtx->sus_res_mcastbcast_filter)))
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530728 {
729 hddLog (VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -0800730 "Set offLoadRequest with SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE");
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530731 offLoadRequest.enableOrDisable =
732 SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE;
733 }
734
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530735 vos_mem_copy(&offLoadRequest.params.hostIpv6Addr,
736 &offLoadRequest.nsOffloadInfo.targetIPv6Addr[0],
737 sizeof(tANI_U8)*SIR_MAC_IPV6_ADDR_LEN);
738
739 hddLog (VOS_TRACE_LEVEL_INFO,
740 "Setting NSOffload with solicitedIp: %pI6, targetIp: %pI6",
741 offLoadRequest.nsOffloadInfo.selfIPv6Addr,
742 offLoadRequest.nsOffloadInfo.targetIPv6Addr[0]);
743
744 //Configure the Firmware with this
745 returnStatus = sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
746 pAdapter->sessionId, &offLoadRequest);
747 if(eHAL_STATUS_SUCCESS != returnStatus)
748 {
749 hddLog(VOS_TRACE_LEVEL_ERROR,
750 FL("Failed to enable HostOffload feature with status: %d"),
751 returnStatus);
752 }
753 vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest));
754 }
755 }
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530756 if (fenable == 1 && !pAdapter->ipv6_notifier_registered)
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530757 {
758 // Register IPv6 notifier to notify if any change in IP
759 // So that we can reconfigure the offload parameters
760 pAdapter->ipv6_notifier.notifier_call =
761 wlan_hdd_ipv6_changed;
762 ret = register_inet6addr_notifier(&pAdapter->ipv6_notifier);
763 if (ret)
764 {
765 hddLog(LOGE, FL("Failed to register IPv6 notifier"));
766 }
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530767 else
768 {
769 hddLog(LOG1, FL("Registered IPv6 notifier"));
770 pAdapter->ipv6_notifier_registered = true;
771 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530772 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530773 }
774 else
775 {
776 hddLog(VOS_TRACE_LEVEL_ERROR,
777 FL("IPv6 dev does not exist. Failed to request NSOffload"));
778 return;
779 }
780 }
781 else
782 {
783 //Disable NSOffload
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530784 if (pAdapter->ipv6_notifier_registered)
785 {
786 hddLog(LOG1, FL("Unregistered IPv6 notifier"));
787 unregister_inet6addr_notifier(&pAdapter->ipv6_notifier);
788 pAdapter->ipv6_notifier_registered = false;
789 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530790 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
791 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
792 offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD;
793
Vinay Krishna Erannab29c6142014-01-07 12:20:51 +0530794 //Disable NSOffload on all slots
795 for (i = 0; i<SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA; i++)
796 {
797 offLoadRequest.nsOffloadInfo.slotIdx = i;
798 if (eHAL_STATUS_SUCCESS !=
Vinay Krishna Eranna911a3b82014-01-07 12:20:51 +0530799 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
800 pAdapter->sessionId, &offLoadRequest))
Vinay Krishna Erannab29c6142014-01-07 12:20:51 +0530801 {
802 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to disable NSOflload"
803 " on slot %d"), i);
804 }
805 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530806 }
807 return;
808}
809#endif
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530810
811void hdd_ipv4_notifier_work_queue(struct work_struct *work)
812{
813 hdd_adapter_t* pAdapter =
814 container_of(work, hdd_adapter_t, ipv4NotifierWorkQueue);
815 hdd_context_t *pHddCtx;
816 int status;
817
818 hddLog(LOG1, FL("Reconfiguring ARP Offload"));
819 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
820 status = wlan_hdd_validate_context(pHddCtx);
821 if (0 != status)
822 {
823 hddLog(LOGE, FL("HDD context is invalid"));
824 return;
825 }
826
827 if ((eConnectionState_Associated ==
828 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)
829 && (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid))
830 {
831 // This invocation being part of the IPv4 registration callback,
832 // we are passing second parameter as 2 to avoid registration
833 // of IPv4 notifier again.
834 hdd_conf_arp_offload(pAdapter, 2);
835 }
836}
837
838static int wlan_hdd_ipv4_changed(struct notifier_block *nb,
839 unsigned long data, void *arg)
840{
841 struct in_ifaddr *ifa = (struct in_ifaddr *)arg;
842 struct in_ifaddr **ifap = NULL;
843 struct in_device *in_dev;
844
845 struct net_device *ndev = ifa->ifa_dev->dev;
846 hdd_adapter_t *pAdapter =
847 container_of(nb, struct hdd_adapter_s, ipv4_notifier);
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +0530848 hdd_context_t *pHddCtx;
849 int status;
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530850 if (pAdapter && pAdapter->dev == ndev)
851 {
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +0530852 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
853 status = wlan_hdd_validate_context(pHddCtx);
854 if (0 != status)
855 {
856 hddLog(LOGE, FL("HDD context is invalid"));
857 return NOTIFY_DONE;
858 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530859 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
860 {
861 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
862 ifap = &ifa->ifa_next)
863 {
864 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
865 {
866 break; /* found */
867 }
868 }
869 }
870 if(ifa && ifa->ifa_local)
871 {
872 schedule_work(&pAdapter->ipv4NotifierWorkQueue);
873 }
874 }
875
876 return NOTIFY_DONE;
877}
878
879/**----------------------------------------------------------------------------
880
881 \brief hdd_conf_arp_offload() - Configure ARP offload
882
883 Called during SUSPEND to configure the ARP offload (MC BC filter) which
884 reduces power consumption.
885
886 \param - pAdapter -Adapter context for which ARP offload is to be configured
887 \param - fenable - 0 - disable.
888 1 - enable. (with IPv4 notifier registration)
889 2 - enable. (without IPv4 notifier registration)
890
891 \return -
892 VOS_STATUS_SUCCESS - on successful operation
893 VOS_STATUS_E_FAILURE - on failure of operation
894-----------------------------------------------------------------------------*/
895VOS_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, int fenable)
Jeff Johnson295189b2012-06-20 16:38:30 -0700896{
897 struct in_ifaddr **ifap = NULL;
898 struct in_ifaddr *ifa = NULL;
899 struct in_device *in_dev;
900 int i = 0;
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530901 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700902 tSirHostOffloadReq offLoadRequest;
Yathish9f22e662012-12-10 14:21:35 -0800903 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700904
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530905 hddLog(VOS_TRACE_LEVEL_ERROR, FL(" fenable = %d \n"), fenable);
Jeff Johnson295189b2012-06-20 16:38:30 -0700906
Jeff Johnson295189b2012-06-20 16:38:30 -0700907 if(fenable)
908 {
909 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
910 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530911 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700912 ifap = &ifa->ifa_next)
913 {
914 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
915 {
916 break; /* found */
917 }
918 }
919 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700920 if(ifa && ifa->ifa_local)
921 {
922 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
923 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
924
Arif Hussain6d2a3322013-11-17 19:50:10 -0800925 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700926
Amar Singhald53568e2013-09-26 11:03:45 -0700927 if (((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
928 pHddCtx->sus_res_mcastbcast_filter) ||
929 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
930 pHddCtx->sus_res_mcastbcast_filter)) &&
931 (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid))
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700932 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530933 offLoadRequest.enableOrDisable =
Amar Singhald53568e2013-09-26 11:03:45 -0700934 SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
935 hddLog(VOS_TRACE_LEVEL_INFO,
936 "offload: inside arp offload conditional check");
Jeff Johnson295189b2012-06-20 16:38:30 -0700937 }
Amar Singhald53568e2013-09-26 11:03:45 -0700938
939 hddLog(VOS_TRACE_LEVEL_INFO, "offload: arp filter programmed = %d",
940 offLoadRequest.enableOrDisable);
941
Jeff Johnson295189b2012-06-20 16:38:30 -0700942 //converting u32 to IPV4 address
943 for(i = 0 ; i < 4; i++)
944 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530945 offLoadRequest.params.hostIpv4Addr[i] =
Jeff Johnson295189b2012-06-20 16:38:30 -0700946 (ifa->ifa_local >> (i*8) ) & 0xFF ;
947 }
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530948 hddLog(VOS_TRACE_LEVEL_INFO, " Enable SME HostOffload: %d.%d.%d.%d",
Jeff Johnson295189b2012-06-20 16:38:30 -0700949 offLoadRequest.params.hostIpv4Addr[0],
950 offLoadRequest.params.hostIpv4Addr[1],
951 offLoadRequest.params.hostIpv4Addr[2],
952 offLoadRequest.params.hostIpv4Addr[3]);
953
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530954 if (eHAL_STATUS_SUCCESS !=
955 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
956 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700957 {
958 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to enable HostOffload "
Arif Hussain6d2a3322013-11-17 19:50:10 -0800959 "feature", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700960 return VOS_STATUS_E_FAILURE;
961 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700962 }
963 else
964 {
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530965 hddLog(VOS_TRACE_LEVEL_INFO, FL("IP Address is not assigned\n"));
Jeff Johnson295189b2012-06-20 16:38:30 -0700966 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530967
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +0530968 if (fenable == 1 && !pAdapter->ipv4_notifier_registered)
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530969 {
970 // Register IPv4 notifier to notify if any change in IP
971 // So that we can reconfigure the offload parameters
972 pAdapter->ipv4_notifier.notifier_call =
973 wlan_hdd_ipv4_changed;
974 ret = register_inetaddr_notifier(&pAdapter->ipv4_notifier);
975 if (ret)
976 {
977 hddLog(LOGE, FL("Failed to register IPv4 notifier"));
978 }
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +0530979 else
980 {
981 hddLog(LOG1, FL("Registered IPv4 notifier"));
982 pAdapter->ipv4_notifier_registered = true;
983 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530984 }
985 return VOS_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -0700986 }
987 else
988 {
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +0530989 if (pAdapter->ipv4_notifier_registered)
990 {
991 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
992 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
993 pAdapter->ipv4_notifier_registered = false;
994 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700995 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
996 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
997 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
998
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530999 if (eHAL_STATUS_SUCCESS !=
1000 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1001 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -07001002 {
1003 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to disable host "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001004 "offload feature", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001005 return VOS_STATUS_E_FAILURE;
1006 }
1007 return VOS_STATUS_SUCCESS;
1008 }
1009}
1010
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301011/*
1012 * This function is called before setting mcbc filters
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301013 * to modify filter value considering Different Offloads
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301014*/
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301015void hdd_mcbc_filter_modification(hdd_context_t* pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301016 tANI_U8 *pMcBcFilter)
1017{
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301018 if (NULL == pHddCtx)
1019 {
1020 hddLog(VOS_TRACE_LEVEL_ERROR, FL("NULL HDD context passed"));
1021 return;
1022 }
1023
1024 *pMcBcFilter = pHddCtx->configuredMcastBcastFilter;
1025 if (pHddCtx->cfg_ini->fhostArpOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301026 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301027 /* ARP offload is enabled, do not block bcast packets at RXP
1028 * Will be using Bitmasking to reset the filter. As we have
1029 * disable Broadcast filtering, Anding with the negation
1030 * of Broadcast BIT
1031 */
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301032 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301033 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301034
1035#ifdef WLAN_NS_OFFLOAD
1036 if (pHddCtx->cfg_ini->fhostNSOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301037 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301038 /* NS offload is enabled, do not block mcast packets at RXP
1039 * Will be using Bitmasking to reset the filter. As we have
1040 * disable Multicast filtering, Anding with the negation
1041 * of Multicast BIT
1042 */
1043 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301044 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301045#endif
1046
1047 pHddCtx->configuredMcastBcastFilter = *pMcBcFilter;
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301048}
1049
Jeff Johnson295189b2012-06-20 16:38:30 -07001050void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter)
1051{
1052 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001053 tpSirWlanSetRxpFilters wlanRxpFilterParam =
1054 vos_mem_malloc(sizeof(tSirWlanSetRxpFilters));
1055 if(NULL == wlanRxpFilterParam)
1056 {
1057 hddLog(VOS_TRACE_LEVEL_FATAL,
1058 "%s: vos_mem_alloc failed ", __func__);
1059 return;
1060 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001061 hddLog(VOS_TRACE_LEVEL_INFO,
1062 "%s: Configuring Mcast/Bcast Filter Setting. setfilter %d", __func__, setfilter);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301063 if (TRUE == setfilter)
1064 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301065 hdd_mcbc_filter_modification(pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301066 &wlanRxpFilterParam->configuredMcstBcstFilterSetting);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301067 }
1068 else
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301069 {
1070 /*Use the current configured value to clear*/
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301071 wlanRxpFilterParam->configuredMcstBcstFilterSetting =
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301072 pHddCtx->configuredMcastBcastFilter;
1073 }
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301074
Jeff Johnson295189b2012-06-20 16:38:30 -07001075 wlanRxpFilterParam->setMcstBcstFilter = setfilter;
Jeff Johnson295189b2012-06-20 16:38:30 -07001076 halStatus = sme_ConfigureRxpFilter(pHddCtx->hHal, wlanRxpFilterParam);
Chilam Ngc4244af2013-04-01 15:37:32 -07001077 if (eHAL_STATUS_SUCCESS != halStatus)
1078 vos_mem_free(wlanRxpFilterParam);
Jeff Johnson295189b2012-06-20 16:38:30 -07001079 if(setfilter && (eHAL_STATUS_SUCCESS == halStatus))
1080 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
1081}
1082
Jeff Johnson295189b2012-06-20 16:38:30 -07001083static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx,
1084 hdd_adapter_t *pAdapter)
1085{
1086 eHalStatus halStatus = eHAL_STATUS_FAILURE;
1087 tpSirWlanSuspendParam wlanSuspendParam =
1088 vos_mem_malloc(sizeof(tSirWlanSuspendParam));
1089
Amar Singhald53568e2013-09-26 11:03:45 -07001090 if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid) {
1091 pHddCtx->sus_res_mcastbcast_filter =
1092 pHddCtx->configuredMcastBcastFilter;
1093 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
1094 hddLog(VOS_TRACE_LEVEL_INFO, "offload: hdd_conf_suspend_ind");
1095 hddLog(VOS_TRACE_LEVEL_INFO, "configuredMCastBcastFilter saved = %d",
1096 pHddCtx->configuredMcastBcastFilter);
1097
1098 }
1099
Amar Singhal49fdfd52013-08-13 13:25:12 -07001100
Jeff Johnson295189b2012-06-20 16:38:30 -07001101 if(NULL == wlanSuspendParam)
1102 {
1103 hddLog(VOS_TRACE_LEVEL_FATAL,
1104 "%s: vos_mem_alloc failed ", __func__);
1105 return;
1106 }
1107
Amar Singhald53568e2013-09-26 11:03:45 -07001108 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001109 "%s: send wlan suspend indication", __func__);
1110
1111 if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER))
1112 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301113 //Configure supported OffLoads
1114 hdd_conf_hostoffload(pAdapter, TRUE);
1115 wlanSuspendParam->configuredMcstBcstFilterSetting = pHddCtx->configuredMcastBcastFilter;
Jeff Johnson295189b2012-06-20 16:38:30 -07001116
1117#ifdef WLAN_FEATURE_PACKET_FILTERING
madan mohan koyyalamudibfd9cef2013-07-01 18:39:37 +05301118 /* During suspend, configure MC Addr list filter to the firmware
1119 * function takes care of checking necessary conditions before
1120 * configuring.
1121 */
1122 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001123#endif
1124 }
1125
1126 halStatus = sme_ConfigureSuspendInd(pHddCtx->hHal, wlanSuspendParam);
1127 if(eHAL_STATUS_SUCCESS == halStatus)
1128 {
1129 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
Chilam Ngc4244af2013-04-01 15:37:32 -07001130 } else {
1131 vos_mem_free(wlanSuspendParam);
Jeff Johnson295189b2012-06-20 16:38:30 -07001132 }
1133}
1134
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301135static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001136{
Chilam Ngc4244af2013-04-01 15:37:32 -07001137 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Yathish9f22e662012-12-10 14:21:35 -08001138 hdd_context_t* pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Chilam Ngc4244af2013-04-01 15:37:32 -07001139 tpSirWlanResumeParam wlanResumeParam;
Jeff Johnson295189b2012-06-20 16:38:30 -07001140
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301141 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001142 "%s: send wlan resume indication", __func__);
1143
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301144 wlanResumeParam = vos_mem_malloc(sizeof(tSirWlanResumeParam));
1145
1146 if (NULL == wlanResumeParam)
Jeff Johnson295189b2012-06-20 16:38:30 -07001147 {
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301148 hddLog(VOS_TRACE_LEVEL_FATAL,
1149 "%s: memory allocation failed for wlanResumeParam ", __func__);
1150 return;
Jeff Johnson295189b2012-06-20 16:38:30 -07001151 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001152
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301153 //Disable supported OffLoads
1154 hdd_conf_hostoffload(pAdapter, FALSE);
1155
1156 wlanResumeParam->configuredMcstBcstFilterSetting =
1157 pHddCtx->configuredMcastBcastFilter;
1158 halStatus = sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam);
1159 if (eHAL_STATUS_SUCCESS != halStatus)
1160 {
1161 vos_mem_free(wlanResumeParam);
1162 }
1163
1164 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
1165
Amar Singhalf8ba2b82013-12-02 12:54:38 -08001166 if (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid) {
1167 pHddCtx->configuredMcastBcastFilter =
1168 pHddCtx->sus_res_mcastbcast_filter;
1169 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_FALSE;
1170 }
Amar Singhald53568e2013-09-26 11:03:45 -07001171
1172 hddLog(VOS_TRACE_LEVEL_INFO,
1173 "offload: in hdd_conf_resume_ind, restoring configuredMcastBcastFilter");
1174 hddLog(VOS_TRACE_LEVEL_INFO, "configuredMcastBcastFilter = %d",
1175 pHddCtx->configuredMcastBcastFilter);
Amar Singhal49fdfd52013-08-13 13:25:12 -07001176
Chilam Ngc4244af2013-04-01 15:37:32 -07001177
madan mohan koyyalamudibfd9cef2013-07-01 18:39:37 +05301178#ifdef WLAN_FEATURE_PACKET_FILTERING
1179 /* Filer was applied during suspend inditication
1180 * clear it when we resume.
1181 */
1182 wlan_hdd_set_mc_addr_list(pAdapter, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001183#endif
1184}
Jeff Johnson295189b2012-06-20 16:38:30 -07001185
Jeff Johnson295189b2012-06-20 16:38:30 -07001186//Suspend routine registered with Android OS
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001187void hdd_suspend_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001188{
1189 hdd_context_t *pHddCtx = NULL;
1190 v_CONTEXT_t pVosContext = NULL;
1191
Jeff Johnson295189b2012-06-20 16:38:30 -07001192 VOS_STATUS status;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301193 hdd_adapter_t *pAdapter = NULL;
1194 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301195 bool hdd_enter_bmps = FALSE;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001196
Jeff Johnson295189b2012-06-20 16:38:30 -07001197 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__);
1198
1199 //Get the global VOSS context.
1200 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1201 if(!pVosContext) {
1202 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1203 return;
1204 }
1205
1206 //Get the HDD context.
1207 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1208
1209 if(!pHddCtx) {
1210 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1211 return;
1212 }
1213
1214 if (pHddCtx->isLogpInProgress) {
1215 hddLog(VOS_TRACE_LEVEL_ERROR,
1216 "%s: Ignore suspend wlan, LOGP in progress!", __func__);
1217 return;
1218 }
1219
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301220 hdd_set_pwrparams(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001221 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1222 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1223 {
1224 pAdapter = pAdapterNode->pAdapter;
1225 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001226 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001227 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
1228
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001229 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001230 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1231 pAdapterNode = pNext;
1232 continue;
1233 }
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301234 /* Avoid multiple enter/exit BMPS in this while loop using
1235 * hdd_enter_bmps flag
1236 */
1237 if (FALSE == hdd_enter_bmps && (BMPS == pmcGetPmcState(pHddCtx->hHal)))
1238 {
1239 hdd_enter_bmps = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001240
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301241 /* If device was already in BMPS, and dynamic DTIM is set,
1242 * exit(set the device to full power) and enter BMPS again
1243 * to reflect new DTIM value */
1244 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
1245
1246 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
1247
1248 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1249 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001250#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1251 if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1252 {
1253 //stop the interface before putting the chip to standby
1254 netif_tx_disable(pAdapter->dev);
1255 netif_carrier_off(pAdapter->dev);
1256 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301257 else if (pHddCtx->cfg_ini->nEnableSuspend ==
Jeff Johnson295189b2012-06-20 16:38:30 -07001258 WLAN_MAP_SUSPEND_TO_DEEP_SLEEP)
1259 {
1260 //Execute deep sleep procedure
1261 hdd_enter_deep_sleep(pHddCtx, pAdapter);
1262 }
1263#endif
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301264
1265 /*Suspend notification sent down to driver*/
1266 hdd_conf_suspend_ind(pHddCtx, pAdapter);
1267
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301268 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1269 pAdapterNode = pNext;
1270 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301271 pHddCtx->hdd_wlan_suspended = TRUE;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301272
Jeff Johnson295189b2012-06-20 16:38:30 -07001273#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1274 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1275 {
1276 hdd_enter_standby(pHddCtx);
1277 }
1278#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001279
1280 return;
1281}
1282
1283static void hdd_PowerStateChangedCB
1284(
1285 v_PVOID_t callbackContext,
1286 tPmcState newState
1287)
1288{
1289 hdd_context_t *pHddCtx = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07001290 /* if the driver was not in BMPS during early suspend,
1291 * the dynamic DTIM is now updated at Riva */
1292 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended
1293 && pHddCtx->cfg_ini->enableDynamicDTIM
1294 && (pHddCtx->hdd_ignore_dtim_enabled == FALSE))
1295 {
1296 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1297 }
1298 spin_lock(&pHddCtx->filter_lock);
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301299 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended)
1300 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001301 spin_unlock(&pHddCtx->filter_lock);
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301302 if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid)
1303 {
Amar Singhald53568e2013-09-26 11:03:45 -07001304 pHddCtx->sus_res_mcastbcast_filter =
1305 pHddCtx->configuredMcastBcastFilter;
1306 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
1307
1308 hddLog(VOS_TRACE_LEVEL_INFO, "offload: callback to associated");
1309 hddLog(VOS_TRACE_LEVEL_INFO, "saving configuredMcastBcastFilter = %d",
1310 pHddCtx->configuredMcastBcastFilter);
1311 hddLog(VOS_TRACE_LEVEL_INFO,
1312 "offload: calling hdd_conf_mcastbcast_filter");
1313
1314 }
1315
Jeff Johnson295189b2012-06-20 16:38:30 -07001316 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001317 if(pHddCtx->hdd_mcastbcast_filter_set != TRUE)
1318 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__);
1319 }
Amar Singhal49fdfd52013-08-13 13:25:12 -07001320 else
Mihir Shete793209f2014-01-06 11:01:12 +05301321 {
1322 /* Android framework can send resume request when the WCN chip is
1323 * in IMPS mode. When the chip exits IMPS mode the firmware will
1324 * restore all the registers to the state they were before the chip
1325 * entered IMPS and so our hardware filter settings confgured by the
1326 * resume request will be lost. So reconfigure the filters on detecting
1327 * a change in the power state of the WCN chip.
1328 */
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301329 spin_unlock(&pHddCtx->filter_lock);
Mihir Shete793209f2014-01-06 11:01:12 +05301330 if (IMPS != newState)
1331 {
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301332 spin_lock(&pHddCtx->filter_lock);
Mihir Shete793209f2014-01-06 11:01:12 +05301333 if (FALSE == pHddCtx->hdd_wlan_suspended)
1334 {
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301335 spin_unlock(&pHddCtx->filter_lock);
Mihir Shete793209f2014-01-06 11:01:12 +05301336 hddLog(VOS_TRACE_LEVEL_INFO,
1337 "Not in IMPS/BMPS and suspended state");
1338 hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
1339 }
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301340 else
1341 {
1342 spin_unlock(&pHddCtx->filter_lock);
1343 }
Mihir Shete793209f2014-01-06 11:01:12 +05301344 }
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301345 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001346}
1347
1348
1349
1350void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx)
1351{
1352 v_CONTEXT_t pVosContext;
1353 tHalHandle smeContext;
1354
1355 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1356 if (NULL == pVosContext)
1357 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001358 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001359 return;
1360 }
1361 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1362 if (NULL == smeContext)
1363 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001364 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001365 return;
1366 }
1367
1368 spin_lock_init(&pHddCtx->filter_lock);
1369 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1370 pHddCtx->cfg_ini->nEnableSuspend)
1371 {
1372 pmcRegisterDeviceStateUpdateInd(smeContext,
1373 hdd_PowerStateChangedCB, pHddCtx);
1374 }
1375}
1376
1377void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx)
1378{
1379 v_CONTEXT_t pVosContext;
1380 tHalHandle smeContext;
1381
1382 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1383 if (NULL == pVosContext)
1384 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001385 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001386 return;
1387 }
1388 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1389 if (NULL == smeContext)
1390 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001391 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001392 return;
1393 }
1394
1395 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1396 pHddCtx->cfg_ini->nEnableSuspend)
1397 {
1398 pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB);
1399 }
1400}
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301401
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301402#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301403void hdd_conf_gtk_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301404{
1405 eHalStatus ret;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301406 tSirGtkOffloadParams hddGtkOffloadReqParams;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301407 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1408
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301409 if(fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301410 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301411 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1412 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags ))
1413 {
1414 vos_mem_copy(&hddGtkOffloadReqParams,
1415 &pHddStaCtx->gtkOffloadReqParams,
1416 sizeof (tSirGtkOffloadParams));
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301417
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301418 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1419 &hddGtkOffloadReqParams, pAdapter->sessionId);
1420 if (eHAL_STATUS_SUCCESS != ret)
1421 {
1422 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1423 "%s: sme_SetGTKOffload failed, returned %d",
1424 __func__, ret);
1425 return;
1426 }
1427
1428 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1429 "%s: sme_SetGTKOffload successfull", __func__);
1430 }
1431
1432 }
1433 else
1434 {
1435 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1436 (0 == memcmp(&pHddStaCtx->gtkOffloadReqParams.bssId,
1437 &pHddStaCtx->conn_info.bssId, WNI_CFG_BSSID_LEN)) &&
1438 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags))
1439 {
1440
1441 /* Host driver has previously offloaded GTK rekey */
1442 ret = sme_GetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301443 wlan_hdd_cfg80211_update_replayCounterCallback,
1444 pAdapter, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301445 if (eHAL_STATUS_SUCCESS != ret)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301446
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301447 {
1448 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1449 "%s: sme_GetGTKOffload failed, returned %d",
1450 __func__, ret);
1451 return;
1452 }
1453 else
1454 {
1455 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1456 "%s: sme_GetGTKOffload successful",
1457 __func__);
1458
1459 /* Sending GTK offload dissable */
1460 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
1461 sizeof (tSirGtkOffloadParams));
1462 hddGtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE;
1463 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301464 &hddGtkOffloadReqParams, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301465 if (eHAL_STATUS_SUCCESS != ret)
1466 {
1467 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1468 "%s: failed to dissable GTK offload, returned %d",
1469 __func__, ret);
1470 return;
1471 }
1472 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1473 "%s: successfully dissabled GTK offload request to HAL",
1474 __func__);
1475 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301476 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301477 }
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301478 return;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301479}
1480#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
Jeff Johnson295189b2012-06-20 16:38:30 -07001481
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001482void hdd_resume_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001483{
1484 hdd_context_t *pHddCtx = NULL;
1485 hdd_adapter_t *pAdapter = NULL;
1486 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1487 VOS_STATUS status;
1488 v_CONTEXT_t pVosContext = NULL;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001489
Jeff Johnson295189b2012-06-20 16:38:30 -07001490 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
1491
1492 //Get the global VOSS context.
1493 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1494 if(!pVosContext) {
1495 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1496 return;
1497 }
1498
1499 //Get the HDD context.
1500 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1501
1502 if(!pHddCtx) {
1503 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1504 return;
1505 }
1506
1507 if (pHddCtx->isLogpInProgress) {
1508 hddLog(VOS_TRACE_LEVEL_INFO,
1509 "%s: Ignore resume wlan, LOGP in progress!", __func__);
1510 return;
1511 }
1512
Jeff Johnson295189b2012-06-20 16:38:30 -07001513 pHddCtx->hdd_wlan_suspended = FALSE;
1514 /*loop through all adapters. Concurrency */
1515 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1516
1517 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1518 {
1519 pAdapter = pAdapterNode->pAdapter;
1520 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001521 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001522 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001523 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001524 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1525 pAdapterNode = pNext;
1526 continue;
1527 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301528
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301529
Jeff Johnson295189b2012-06-20 16:38:30 -07001530#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1531 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP)
1532 {
1533 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__);
1534 hdd_exit_deep_sleep(pAdapter);
1535 }
1536#endif
1537
1538 if(pHddCtx->hdd_ignore_dtim_enabled == TRUE)
1539 {
1540 /*Switch back to DTIM 1*/
1541 tSirSetPowerParamsReq powerRequest = { 0 };
1542
1543 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
1544 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07001545 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001546
1547 /*Disabled ModulatedDTIM if enabled on suspend*/
1548 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1549 powerRequest.uDTIMPeriod = 0;
1550
1551 /* Update ignoreDTIM and ListedInterval in CFG with default values */
1552 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1553 NULL, eANI_BOOLEAN_FALSE);
1554 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1555 NULL, eANI_BOOLEAN_FALSE);
1556
1557 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001558 "Switch to DTIM%d",powerRequest.uListenInterval);
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08001559 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001560
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301561 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
1562 {
1563 /* put the device into full power */
1564 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001565
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301566 /* put the device back into BMPS */
1567 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
Jeff Johnson295189b2012-06-20 16:38:30 -07001568
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301569 pHddCtx->hdd_ignore_dtim_enabled = FALSE;
1570 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001571 }
1572
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301573 hdd_conf_resume_ind(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001574 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1575 pAdapterNode = pNext;
1576 }
1577
1578#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1579 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY)
1580 {
1581 hdd_exit_standby(pHddCtx);
1582 }
1583#endif
1584
Jeff Johnson295189b2012-06-20 16:38:30 -07001585 return;
1586}
1587
Jeff Johnson295189b2012-06-20 16:38:30 -07001588VOS_STATUS hdd_wlan_reset_initialization(void)
1589{
Jeff Johnson295189b2012-06-20 16:38:30 -07001590 v_CONTEXT_t pVosContext = NULL;
1591
1592 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1593
1594 //Get the global VOSS context.
1595 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1596 if(!pVosContext)
1597 {
1598 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1599 return VOS_STATUS_E_FAILURE;
1600 }
1601
1602 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__);
1603
1604 // Prevent the phone from going to sleep
1605 hdd_prevent_suspend();
1606
Jeff Johnson295189b2012-06-20 16:38:30 -07001607 return VOS_STATUS_SUCCESS;
1608}
1609
1610
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001611/*
1612 * Based on the ioctl command recieved by HDD, put WLAN driver
1613 * into the quiet mode. This is the same as the early suspend
1614 * notification that driver used to listen
1615 */
1616void hdd_set_wlan_suspend_mode(bool suspend)
Jeff Johnson295189b2012-06-20 16:38:30 -07001617{
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001618 if (suspend)
1619 hdd_suspend_wlan();
1620 else
1621 hdd_resume_wlan();
Jeff Johnson295189b2012-06-20 16:38:30 -07001622}
1623
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001624static void hdd_ssr_timer_init(void)
1625{
1626 init_timer(&ssr_timer);
1627}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001628
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001629static void hdd_ssr_timer_del(void)
1630{
1631 del_timer(&ssr_timer);
1632 ssr_timer_started = false;
1633}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001634
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001635static void hdd_ssr_timer_cb(unsigned long data)
1636{
1637 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD SSR timer expired", __func__);
Sameer Thalappile5637f42013-08-07 15:46:55 -07001638
1639#ifdef WCN_PRONTO
1640 if (wcnss_hardware_type() == WCNSS_PRONTO_HW)
1641 wcnss_pronto_log_debug_regs();
1642#endif
1643
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001644 VOS_BUG(0);
1645}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001646
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001647static void hdd_ssr_timer_start(int msec)
1648{
1649 if(ssr_timer_started)
1650 {
1651 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: trying to start SSR timer when it's running"
1652 ,__func__);
1653 }
1654 ssr_timer.expires = jiffies + msecs_to_jiffies(msec);
1655 ssr_timer.function = hdd_ssr_timer_cb;
1656 add_timer(&ssr_timer);
1657 ssr_timer_started = true;
1658}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001659
Jeff Johnson295189b2012-06-20 16:38:30 -07001660/* the HDD interface to WLAN driver shutdown,
1661 * the primary shutdown function in SSR
1662 */
1663VOS_STATUS hdd_wlan_shutdown(void)
1664{
1665 VOS_STATUS vosStatus;
1666 v_CONTEXT_t pVosContext = NULL;
1667 hdd_context_t *pHddCtx = NULL;
1668 pVosSchedContext vosSchedContext = NULL;
1669
1670 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__);
1671
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001672 /* if re-init never happens, then do SSR1 */
1673 hdd_ssr_timer_init();
1674 hdd_ssr_timer_start(HDD_SSR_BRING_UP_TIME);
1675
Jeff Johnson295189b2012-06-20 16:38:30 -07001676 /* Get the global VOSS context. */
1677 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1678 if(!pVosContext) {
1679 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1680 return VOS_STATUS_E_FAILURE;
1681 }
1682 /* Get the HDD context. */
1683 pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1684 if(!pHddCtx) {
1685 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1686 return VOS_STATUS_E_FAILURE;
1687 }
c_hpothud662a352013-12-26 15:09:12 +05301688
1689 //Stop the traffic monitor timer
1690 if ( VOS_TIMER_STATE_RUNNING ==
1691 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
1692 {
1693 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
1694 }
1695
Jeff Johnson295189b2012-06-20 16:38:30 -07001696 hdd_reset_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001697 /* DeRegister with platform driver as client for Suspend/Resume */
1698 vosStatus = hddDeregisterPmOps(pHddCtx);
1699 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1700 {
1701 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
1702 }
1703
1704 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
1705 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1706 {
1707 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
1708 }
1709
1710 /* Disable IMPS/BMPS as we do not want the device to enter any power
1711 * save mode on its own during reset sequence
1712 */
1713 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1714 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1715 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1716
1717 vosSchedContext = get_vos_sched_ctxt();
1718
1719 /* Wakeup all driver threads */
1720 if(TRUE == pHddCtx->isMcThreadSuspended){
1721 complete(&vosSchedContext->ResumeMcEvent);
1722 pHddCtx->isMcThreadSuspended= FALSE;
1723 }
1724 if(TRUE == pHddCtx->isTxThreadSuspended){
1725 complete(&vosSchedContext->ResumeTxEvent);
1726 pHddCtx->isTxThreadSuspended= FALSE;
1727 }
1728 if(TRUE == pHddCtx->isRxThreadSuspended){
1729 complete(&vosSchedContext->ResumeRxEvent);
1730 pHddCtx->isRxThreadSuspended= FALSE;
1731 }
1732 /* Reset the Suspend Variable */
1733 pHddCtx->isWlanSuspended = FALSE;
1734
1735 /* Stop all the threads; we do not want any messages to be a processed,
1736 * any more and the best way to ensure that is to terminate the threads
1737 * gracefully.
1738 */
1739 /* Wait for MC to exit */
1740 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
1741 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
1742 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
1743 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
Mihir Shete165143a2013-12-19 09:06:13 +05301744 wait_for_completion(&vosSchedContext->McShutdown);
Jeff Johnson295189b2012-06-20 16:38:30 -07001745
1746 /* Wait for TX to exit */
1747 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
1748 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
1749 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
1750 wake_up_interruptible(&vosSchedContext->txWaitQueue);
Mihir Shete165143a2013-12-19 09:06:13 +05301751 wait_for_completion(&vosSchedContext->TxShutdown);
Jeff Johnson295189b2012-06-20 16:38:30 -07001752
1753 /* Wait for RX to exit */
1754 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
1755 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
1756 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
1757 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
Mihir Shete165143a2013-12-19 09:06:13 +05301758 wait_for_completion(&vosSchedContext->RxShutdown);
Jeff Johnson295189b2012-06-20 16:38:30 -07001759
1760#ifdef WLAN_BTAMP_FEATURE
1761 vosStatus = WLANBAP_Stop(pVosContext);
1762 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1763 {
1764 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1765 "%s: Failed to stop BAP",__func__);
1766 }
1767#endif //WLAN_BTAMP_FEATURE
1768 vosStatus = vos_wda_shutdown(pVosContext);
1769 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1770
1771 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
1772 /* Stop SME - Cannot invoke vos_stop as vos_stop relies
1773 * on threads being running to process the SYS Stop
1774 */
Kiet Lama72a2322013-11-15 11:18:11 +05301775 vosStatus = sme_Stop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
Jeff Johnson295189b2012-06-20 16:38:30 -07001776 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1777
1778 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
1779 /* Stop MAC (PE and HAL) */
1780 vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
1781 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1782
1783 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
1784 /* Stop TL */
1785 vosStatus = WLANTL_Stop(pVosContext);
1786 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1787
Jeff Johnson295189b2012-06-20 16:38:30 -07001788 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001789 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__);
1790 /* Clean up message queues of TX and MC thread */
1791 vos_sched_flush_mc_mqs(vosSchedContext);
1792 vos_sched_flush_tx_mqs(vosSchedContext);
1793 vos_sched_flush_rx_mqs(vosSchedContext);
1794
1795 /* Deinit all the TX and MC queues */
1796 vos_sched_deinit_mqs(vosSchedContext);
1797 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__);
1798
1799 /* shutdown VOSS */
1800 vos_shutdown(pVosContext);
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05301801
1802 /*mac context has already been released in mac_close call
1803 so setting it to NULL in hdd context*/
1804 pHddCtx->hHal = (tHalHandle)NULL;
1805
Jeff Johnson295189b2012-06-20 16:38:30 -07001806 if (free_riva_power_on_lock("wlan"))
1807 {
1808 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
1809 __func__);
1810 }
1811 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete"
1812 ,__func__);
1813 return VOS_STATUS_SUCCESS;
1814}
1815
1816
1817
1818/* the HDD interface to WLAN driver re-init.
1819 * This is called to initialize/start WLAN driver after a shutdown.
1820 */
1821VOS_STATUS hdd_wlan_re_init(void)
1822{
1823 VOS_STATUS vosStatus;
1824 v_CONTEXT_t pVosContext = NULL;
1825 hdd_context_t *pHddCtx = NULL;
1826 eHalStatus halStatus;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07001827#ifdef HAVE_WCNSS_CAL_DOWNLOAD
1828 int max_retries = 0;
1829#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001830#ifdef WLAN_BTAMP_FEATURE
1831 hdd_config_t *pConfig = NULL;
1832 WLANBAP_ConfigType btAmpConfig;
1833#endif
1834
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001835 hdd_ssr_timer_del();
Jeff Johnson295189b2012-06-20 16:38:30 -07001836 hdd_prevent_suspend();
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001837
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07001838#ifdef HAVE_WCNSS_CAL_DOWNLOAD
1839 /* wait until WCNSS driver downloads NV */
1840 while (!wcnss_device_ready() && 5 >= ++max_retries) {
1841 msleep(1000);
1842 }
1843 if (max_retries >= 5) {
1844 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
1845 goto err_re_init;
1846 }
1847#endif
1848
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07001849 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, TRUE);
1850
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001851 /* The driver should always be initialized in STA mode after SSR */
1852 hdd_set_conparam(0);
1853
Jeff Johnson295189b2012-06-20 16:38:30 -07001854 /* Re-open VOSS, it is a re-open b'se control transport was never closed. */
1855 vosStatus = vos_open(&pVosContext, 0);
1856 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1857 {
1858 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
1859 goto err_re_init;
1860 }
1861
1862 /* Get the HDD context. */
1863 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1864 if(!pHddCtx)
1865 {
1866 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1867 goto err_vosclose;
1868 }
1869
1870 /* Save the hal context in Adapter */
1871 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
1872 if ( NULL == pHddCtx->hHal )
1873 {
1874 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
1875 goto err_vosclose;
1876 }
1877
1878 /* Set the SME configuration parameters. */
1879 vosStatus = hdd_set_sme_config(pHddCtx);
1880 if ( VOS_STATUS_SUCCESS != vosStatus )
1881 {
1882 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
1883 goto err_vosclose;
1884 }
1885
1886 /* Initialize the WMM module */
1887 vosStatus = hdd_wmm_init(pHddCtx);
1888 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
1889 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001890 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001891 goto err_vosclose;
1892 }
1893
1894 vosStatus = vos_preStart( pHddCtx->pvosContext );
1895 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1896 {
1897 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
1898 goto err_vosclose;
1899 }
1900
1901 /* In the integrated architecture we update the configuration from
1902 the INI file and from NV before vOSS has been started so that
1903 the final contents are available to send down to the cCPU */
1904 /* Apply the cfg.ini to cfg.dat */
1905 if (FALSE == hdd_update_config_dat(pHddCtx))
1906 {
1907 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
1908 goto err_vosclose;
1909 }
1910
1911 /* Set the MAC Address, currently this is used by HAL to add self sta.
1912 * Remove this once self sta is added as part of session open. */
1913 halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID,
1914 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
1915 sizeof(pHddCtx->cfg_ini->intfMacAddr[0]));
1916 if (!HAL_STATUS_SUCCESS(halStatus))
1917 {
1918 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
1919 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus);
1920 goto err_vosclose;
1921 }
1922
1923 /* Start VOSS which starts up the SME/MAC/HAL modules and everything else
1924 Note: Firmware image will be read and downloaded inside vos_start API */
1925 vosStatus = vos_start( pVosContext );
1926 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1927 {
1928 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
1929 goto err_vosclose;
1930 }
1931
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07001932 /* Exchange capability info between Host and FW and also get versioning info from FW */
1933 hdd_exchange_version_and_caps(pHddCtx);
1934
Jeff Johnson295189b2012-06-20 16:38:30 -07001935 vosStatus = hdd_post_voss_start_config( pHddCtx );
1936 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1937 {
1938 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
1939 __func__);
1940 goto err_vosstop;
1941 }
1942
1943#ifdef WLAN_BTAMP_FEATURE
1944 vosStatus = WLANBAP_Open(pVosContext);
1945 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1946 {
1947 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1948 "%s: Failed to open BAP",__func__);
1949 goto err_vosstop;
1950 }
1951 vosStatus = BSL_Init(pVosContext);
1952 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1953 {
1954 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1955 "%s: Failed to Init BSL",__func__);
1956 goto err_bap_close;
1957 }
1958 vosStatus = WLANBAP_Start(pVosContext);
1959 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1960 {
1961 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1962 "%s: Failed to start TL",__func__);
1963 goto err_bap_close;
1964 }
1965 pConfig = pHddCtx->cfg_ini;
1966 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
1967 vosStatus = WLANBAP_SetConfig(&btAmpConfig);
1968#endif //WLAN_BTAMP_FEATURE
1969
1970 /* Restart all adapters */
1971 hdd_start_all_adapters(pHddCtx);
1972 pHddCtx->isLogpInProgress = FALSE;
Sameer Thalappilb511beb2013-09-09 17:11:51 -07001973 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001974 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001975 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001976
1977 /* Register with platform driver as client for Suspend/Resume */
1978 vosStatus = hddRegisterPmOps(pHddCtx);
1979 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1980 {
1981 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
1982 goto err_bap_stop;
1983 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001984 /* Allow the phone to go to sleep */
1985 hdd_allow_suspend();
1986 /* register for riva power on lock */
1987 if (req_riva_power_on_lock("wlan"))
1988 {
1989 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
1990 __func__);
1991 goto err_unregister_pmops;
1992 }
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07001993 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001994 goto success;
1995
1996err_unregister_pmops:
1997 hddDeregisterPmOps(pHddCtx);
1998
1999err_bap_stop:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002000#ifdef CONFIG_HAS_EARLYSUSPEND
2001 hdd_unregister_mcast_bcast_filter(pHddCtx);
2002#endif
2003 hdd_close_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002004#ifdef WLAN_BTAMP_FEATURE
Jeff Johnson32d95a32012-09-10 13:15:23 -07002005 WLANBAP_Stop(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07002006#endif
2007
2008#ifdef WLAN_BTAMP_FEATURE
2009err_bap_close:
2010 WLANBAP_Close(pVosContext);
2011#endif
2012
2013err_vosstop:
2014 vos_stop(pVosContext);
2015
2016err_vosclose:
2017 vos_close(pVosContext);
2018 vos_sched_close(pVosContext);
2019 if (pHddCtx)
2020 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002021 /* Unregister the Net Device Notifier */
2022 unregister_netdevice_notifier(&hdd_netdev_notifier);
2023 /* Clean up HDD Nlink Service */
2024 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07002025#ifdef WLAN_KD_READY_NOTIFIER
2026 nl_srv_exit(pHddCtx->ptt_pid);
2027#else
Jeff Johnson295189b2012-06-20 16:38:30 -07002028 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07002029#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07002030 /* Free up dynamically allocated members inside HDD Adapter */
2031 kfree(pHddCtx->cfg_ini);
2032 pHddCtx->cfg_ini= NULL;
2033
Jeff Johnson295189b2012-06-20 16:38:30 -07002034 wiphy_unregister(pHddCtx->wiphy);
2035 wiphy_free(pHddCtx->wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07002036 }
2037 vos_preClose(&pVosContext);
2038
2039#ifdef MEMORY_DEBUG
2040 vos_mem_exit();
2041#endif
2042
2043err_re_init:
2044 /* Allow the phone to go to sleep */
2045 hdd_allow_suspend();
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07002046 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07002047 VOS_BUG(0);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002048 return -EPERM;
Jeff Johnson295189b2012-06-20 16:38:30 -07002049
2050success:
2051 /* Trigger replay of BTC events */
2052 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
2053 return VOS_STATUS_SUCCESS;
2054}