blob: 9a83efc98fa61a7eb723f05f1af3260ea8840b88 [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"));
572 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
573 status = wlan_hdd_validate_context(pHddCtx);
574 if (0 != status)
575 {
576 hddLog(LOGE, FL("HDD context is invalid"));
577 return;
578 }
579
580 if (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid)
581 {
582 // This invocation being part of the IPv6 registration callback,
583 // we are passing second parameter as 2 to avoid registration
584 // of IPv6 notifier again.
585 hdd_conf_ns_offload(pAdapter, 2);
586 }
587}
588
589static int wlan_hdd_ipv6_changed(struct notifier_block *nb,
590 unsigned long data, void *arg)
591{
592 struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)arg;
593 struct net_device *ndev = ifa->idev->dev;
594 hdd_adapter_t *pAdapter =
595 container_of(nb, struct hdd_adapter_s, ipv6_notifier);
596
597 if (pAdapter && pAdapter->dev == ndev)
598 {
599 schedule_work(&pAdapter->ipv6NotifierWorkQueue);
600 }
601
602 return NOTIFY_DONE;
603}
604
605/**----------------------------------------------------------------------------
606
607 \brief hdd_conf_ns_offload() - Configure NS offload
608
609 Called during SUSPEND to configure the NS offload (MC BC filter) which
610 reduces power consumption.
611
612 \param - pAdapter - Adapter context for which NS offload is to be configured
613 \param - fenable - 0 - disable.
614 1 - enable. (with IPv6 notifier registration)
615 2 - enable. (without IPv6 notifier registration)
616
617 \return - void
618
619 ---------------------------------------------------------------------------*/
620void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, int fenable)
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530621{
622 struct inet6_dev *in6_dev;
623 struct inet6_ifaddr *ifp;
624 struct list_head *p;
625 tANI_U8 selfIPv6Addr[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA][SIR_MAC_IPV6_ADDR_LEN] = {{0,}};
626 tANI_BOOLEAN selfIPv6AddrValid[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA] = {0};
627 tSirHostOffloadReq offLoadRequest;
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530628 hdd_context_t *pHddCtx;
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530629
630 int i =0;
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530631 int ret =0;
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530632 eHalStatus returnStatus;
633
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530634 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
635
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530636 ENTER();
637 if (fenable)
638 {
639 in6_dev = __in6_dev_get(pAdapter->dev);
640 if (NULL != in6_dev)
641 {
642 //read_lock_bh(&in6_dev->lock);
643 list_for_each(p, &in6_dev->addr_list)
644 {
645 ifp = list_entry(p, struct inet6_ifaddr, if_list);
646 switch(ipv6_addr_src_scope(&ifp->addr))
647 {
648 case IPV6_ADDR_SCOPE_LINKLOCAL:
649 vos_mem_copy(&selfIPv6Addr[0], &ifp->addr.s6_addr,
650 sizeof(ifp->addr.s6_addr));
651 selfIPv6AddrValid[0] = SIR_IPV6_ADDR_VALID;
Hardik Kantilal Patel1341bdf2013-08-22 20:27:15 +0530652 hddLog (VOS_TRACE_LEVEL_INFO,
653 "Found IPV6_ADDR_SCOPE_LINKLOCAL Address : %pI6",
654 selfIPv6Addr[0]);
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530655 break;
656 case IPV6_ADDR_SCOPE_GLOBAL:
657 vos_mem_copy(&selfIPv6Addr[1], &ifp->addr.s6_addr,
658 sizeof(ifp->addr.s6_addr));
Hardik Kantilal Patel1341bdf2013-08-22 20:27:15 +0530659 selfIPv6AddrValid[1] = SIR_IPV6_ADDR_VALID;
660 hddLog (VOS_TRACE_LEVEL_INFO,
661 "Found IPV6_ADDR_SCOPE_GLOBAL Address : %pI6",
662 selfIPv6Addr[1]);
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530663 break;
664 default:
665 hddLog(LOGE, "The Scope %d is not supported",
666 ipv6_addr_src_scope(&ifp->addr));
667 }
668
669 }
670 //read_unlock_bh(&in6_dev->lock);
671 vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest));
672 for (i =0; i<SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA; i++)
673 {
674 if (selfIPv6AddrValid[i])
675 {
676 //Filling up the request structure
677 /* Filling the selfIPv6Addr with solicited address
678 * A Solicited-Node multicast address is created by
679 * taking the last 24 bits of a unicast or anycast
680 * address and appending them to the prefix
681 *
682 * FF02:0000:0000:0000:0000:0001:FFXX:XX
683 *
684 * here XX is the unicast/anycast bits
685 */
686 offLoadRequest.nsOffloadInfo.selfIPv6Addr[0] = 0xFF;
687 offLoadRequest.nsOffloadInfo.selfIPv6Addr[1] = 0x02;
688 offLoadRequest.nsOffloadInfo.selfIPv6Addr[11] = 0x01;
689 offLoadRequest.nsOffloadInfo.selfIPv6Addr[12] = 0xFF;
690 offLoadRequest.nsOffloadInfo.selfIPv6Addr[13] = selfIPv6Addr[i][13];
691 offLoadRequest.nsOffloadInfo.selfIPv6Addr[14] = selfIPv6Addr[i][14];
692 offLoadRequest.nsOffloadInfo.selfIPv6Addr[15] = selfIPv6Addr[i][15];
693 offLoadRequest.nsOffloadInfo.slotIdx = i;
694
695 vos_mem_copy(&offLoadRequest.nsOffloadInfo.targetIPv6Addr[0],
696 &selfIPv6Addr[i][0], sizeof(tANI_U8)*SIR_MAC_IPV6_ADDR_LEN);
697 vos_mem_copy(&offLoadRequest.nsOffloadInfo.selfMacAddr,
698 &pAdapter->macAddressCurrent.bytes,
699 sizeof(tANI_U8)*SIR_MAC_ADDR_LEN);
700
701 offLoadRequest.nsOffloadInfo.targetIPv6AddrValid[0] = SIR_IPV6_ADDR_VALID;
702 offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD;
703 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
704
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530705 hddLog (VOS_TRACE_LEVEL_INFO,
706 "configuredMcastBcastFilter: %d",pHddCtx->configuredMcastBcastFilter);
707
Kiet Lamc8e1eb52013-10-24 00:30:49 +0530708 if ((VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid)
709 && ((HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST ==
710 pHddCtx->sus_res_mcastbcast_filter) ||
711 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
712 pHddCtx->sus_res_mcastbcast_filter)))
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530713 {
714 hddLog (VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -0800715 "Set offLoadRequest with SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE");
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530716 offLoadRequest.enableOrDisable =
717 SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE;
718 }
719
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530720 vos_mem_copy(&offLoadRequest.params.hostIpv6Addr,
721 &offLoadRequest.nsOffloadInfo.targetIPv6Addr[0],
722 sizeof(tANI_U8)*SIR_MAC_IPV6_ADDR_LEN);
723
724 hddLog (VOS_TRACE_LEVEL_INFO,
725 "Setting NSOffload with solicitedIp: %pI6, targetIp: %pI6",
726 offLoadRequest.nsOffloadInfo.selfIPv6Addr,
727 offLoadRequest.nsOffloadInfo.targetIPv6Addr[0]);
728
729 //Configure the Firmware with this
730 returnStatus = sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
731 pAdapter->sessionId, &offLoadRequest);
732 if(eHAL_STATUS_SUCCESS != returnStatus)
733 {
734 hddLog(VOS_TRACE_LEVEL_ERROR,
735 FL("Failed to enable HostOffload feature with status: %d"),
736 returnStatus);
737 }
738 vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest));
739 }
740 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530741 if (fenable == 1)
742 {
743 // Register IPv6 notifier to notify if any change in IP
744 // So that we can reconfigure the offload parameters
745 pAdapter->ipv6_notifier.notifier_call =
746 wlan_hdd_ipv6_changed;
747 ret = register_inet6addr_notifier(&pAdapter->ipv6_notifier);
748 if (ret)
749 {
750 hddLog(LOGE, FL("Failed to register IPv6 notifier"));
751 }
752 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530753 }
754 else
755 {
756 hddLog(VOS_TRACE_LEVEL_ERROR,
757 FL("IPv6 dev does not exist. Failed to request NSOffload"));
758 return;
759 }
760 }
761 else
762 {
763 //Disable NSOffload
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530764 unregister_inet6addr_notifier(&pAdapter->ipv6_notifier);
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530765 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
766 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
767 offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD;
768
Vinay Krishna Erannab29c6142014-01-07 12:20:51 +0530769 //Disable NSOffload on all slots
770 for (i = 0; i<SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA; i++)
771 {
772 offLoadRequest.nsOffloadInfo.slotIdx = i;
773 if (eHAL_STATUS_SUCCESS !=
Vinay Krishna Eranna911a3b82014-01-07 12:20:51 +0530774 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
775 pAdapter->sessionId, &offLoadRequest))
Vinay Krishna Erannab29c6142014-01-07 12:20:51 +0530776 {
777 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to disable NSOflload"
778 " on slot %d"), i);
779 }
780 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530781 }
782 return;
783}
784#endif
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530785
786void hdd_ipv4_notifier_work_queue(struct work_struct *work)
787{
788 hdd_adapter_t* pAdapter =
789 container_of(work, hdd_adapter_t, ipv4NotifierWorkQueue);
790 hdd_context_t *pHddCtx;
791 int status;
792
793 hddLog(LOG1, FL("Reconfiguring ARP Offload"));
794 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
795 status = wlan_hdd_validate_context(pHddCtx);
796 if (0 != status)
797 {
798 hddLog(LOGE, FL("HDD context is invalid"));
799 return;
800 }
801
802 if ((eConnectionState_Associated ==
803 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)
804 && (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid))
805 {
806 // This invocation being part of the IPv4 registration callback,
807 // we are passing second parameter as 2 to avoid registration
808 // of IPv4 notifier again.
809 hdd_conf_arp_offload(pAdapter, 2);
810 }
811}
812
813static int wlan_hdd_ipv4_changed(struct notifier_block *nb,
814 unsigned long data, void *arg)
815{
816 struct in_ifaddr *ifa = (struct in_ifaddr *)arg;
817 struct in_ifaddr **ifap = NULL;
818 struct in_device *in_dev;
819
820 struct net_device *ndev = ifa->ifa_dev->dev;
821 hdd_adapter_t *pAdapter =
822 container_of(nb, struct hdd_adapter_s, ipv4_notifier);
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +0530823 hdd_context_t *pHddCtx;
824 int status;
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530825 if (pAdapter && pAdapter->dev == ndev)
826 {
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +0530827 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
828 status = wlan_hdd_validate_context(pHddCtx);
829 if (0 != status)
830 {
831 hddLog(LOGE, FL("HDD context is invalid"));
832 return NOTIFY_DONE;
833 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530834 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
835 {
836 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
837 ifap = &ifa->ifa_next)
838 {
839 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
840 {
841 break; /* found */
842 }
843 }
844 }
845 if(ifa && ifa->ifa_local)
846 {
847 schedule_work(&pAdapter->ipv4NotifierWorkQueue);
848 }
849 }
850
851 return NOTIFY_DONE;
852}
853
854/**----------------------------------------------------------------------------
855
856 \brief hdd_conf_arp_offload() - Configure ARP offload
857
858 Called during SUSPEND to configure the ARP offload (MC BC filter) which
859 reduces power consumption.
860
861 \param - pAdapter -Adapter context for which ARP offload is to be configured
862 \param - fenable - 0 - disable.
863 1 - enable. (with IPv4 notifier registration)
864 2 - enable. (without IPv4 notifier registration)
865
866 \return -
867 VOS_STATUS_SUCCESS - on successful operation
868 VOS_STATUS_E_FAILURE - on failure of operation
869-----------------------------------------------------------------------------*/
870VOS_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, int fenable)
Jeff Johnson295189b2012-06-20 16:38:30 -0700871{
872 struct in_ifaddr **ifap = NULL;
873 struct in_ifaddr *ifa = NULL;
874 struct in_device *in_dev;
875 int i = 0;
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530876 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700877 tSirHostOffloadReq offLoadRequest;
Yathish9f22e662012-12-10 14:21:35 -0800878 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700879
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530880 hddLog(VOS_TRACE_LEVEL_ERROR, FL(" fenable = %d \n"), fenable);
Jeff Johnson295189b2012-06-20 16:38:30 -0700881
Jeff Johnson295189b2012-06-20 16:38:30 -0700882 if(fenable)
883 {
884 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
885 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530886 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700887 ifap = &ifa->ifa_next)
888 {
889 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
890 {
891 break; /* found */
892 }
893 }
894 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700895 if(ifa && ifa->ifa_local)
896 {
897 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
898 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
899
Arif Hussain6d2a3322013-11-17 19:50:10 -0800900 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700901
Amar Singhald53568e2013-09-26 11:03:45 -0700902 if (((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
903 pHddCtx->sus_res_mcastbcast_filter) ||
904 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
905 pHddCtx->sus_res_mcastbcast_filter)) &&
906 (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid))
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700907 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530908 offLoadRequest.enableOrDisable =
Amar Singhald53568e2013-09-26 11:03:45 -0700909 SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
910 hddLog(VOS_TRACE_LEVEL_INFO,
911 "offload: inside arp offload conditional check");
Jeff Johnson295189b2012-06-20 16:38:30 -0700912 }
Amar Singhald53568e2013-09-26 11:03:45 -0700913
914 hddLog(VOS_TRACE_LEVEL_INFO, "offload: arp filter programmed = %d",
915 offLoadRequest.enableOrDisable);
916
Jeff Johnson295189b2012-06-20 16:38:30 -0700917 //converting u32 to IPV4 address
918 for(i = 0 ; i < 4; i++)
919 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530920 offLoadRequest.params.hostIpv4Addr[i] =
Jeff Johnson295189b2012-06-20 16:38:30 -0700921 (ifa->ifa_local >> (i*8) ) & 0xFF ;
922 }
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530923 hddLog(VOS_TRACE_LEVEL_INFO, " Enable SME HostOffload: %d.%d.%d.%d",
Jeff Johnson295189b2012-06-20 16:38:30 -0700924 offLoadRequest.params.hostIpv4Addr[0],
925 offLoadRequest.params.hostIpv4Addr[1],
926 offLoadRequest.params.hostIpv4Addr[2],
927 offLoadRequest.params.hostIpv4Addr[3]);
928
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530929 if (eHAL_STATUS_SUCCESS !=
930 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
931 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700932 {
933 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to enable HostOffload "
Arif Hussain6d2a3322013-11-17 19:50:10 -0800934 "feature", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700935 return VOS_STATUS_E_FAILURE;
936 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700937 }
938 else
939 {
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530940 hddLog(VOS_TRACE_LEVEL_INFO, FL("IP Address is not assigned\n"));
Jeff Johnson295189b2012-06-20 16:38:30 -0700941 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530942
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +0530943 if (fenable == 1 && !pAdapter->ipv4_notifier_registered)
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530944 {
945 // Register IPv4 notifier to notify if any change in IP
946 // So that we can reconfigure the offload parameters
947 pAdapter->ipv4_notifier.notifier_call =
948 wlan_hdd_ipv4_changed;
949 ret = register_inetaddr_notifier(&pAdapter->ipv4_notifier);
950 if (ret)
951 {
952 hddLog(LOGE, FL("Failed to register IPv4 notifier"));
953 }
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +0530954 else
955 {
956 hddLog(LOG1, FL("Registered IPv4 notifier"));
957 pAdapter->ipv4_notifier_registered = true;
958 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530959 }
960 return VOS_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -0700961 }
962 else
963 {
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +0530964 if (pAdapter->ipv4_notifier_registered)
965 {
966 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
967 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
968 pAdapter->ipv4_notifier_registered = false;
969 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700970 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
971 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
972 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
973
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530974 if (eHAL_STATUS_SUCCESS !=
975 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
976 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700977 {
978 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to disable host "
Arif Hussain6d2a3322013-11-17 19:50:10 -0800979 "offload feature", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700980 return VOS_STATUS_E_FAILURE;
981 }
982 return VOS_STATUS_SUCCESS;
983 }
984}
985
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530986/*
987 * This function is called before setting mcbc filters
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530988 * to modify filter value considering Different Offloads
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530989*/
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530990void hdd_mcbc_filter_modification(hdd_context_t* pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530991 tANI_U8 *pMcBcFilter)
992{
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530993 if (NULL == pHddCtx)
994 {
995 hddLog(VOS_TRACE_LEVEL_ERROR, FL("NULL HDD context passed"));
996 return;
997 }
998
999 *pMcBcFilter = pHddCtx->configuredMcastBcastFilter;
1000 if (pHddCtx->cfg_ini->fhostArpOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301001 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301002 /* ARP offload is enabled, do not block bcast packets at RXP
1003 * Will be using Bitmasking to reset the filter. As we have
1004 * disable Broadcast filtering, Anding with the negation
1005 * of Broadcast BIT
1006 */
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301007 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301008 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301009
1010#ifdef WLAN_NS_OFFLOAD
1011 if (pHddCtx->cfg_ini->fhostNSOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301012 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301013 /* NS offload is enabled, do not block mcast packets at RXP
1014 * Will be using Bitmasking to reset the filter. As we have
1015 * disable Multicast filtering, Anding with the negation
1016 * of Multicast BIT
1017 */
1018 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301019 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301020#endif
1021
1022 pHddCtx->configuredMcastBcastFilter = *pMcBcFilter;
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301023}
1024
Jeff Johnson295189b2012-06-20 16:38:30 -07001025void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter)
1026{
1027 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001028 tpSirWlanSetRxpFilters wlanRxpFilterParam =
1029 vos_mem_malloc(sizeof(tSirWlanSetRxpFilters));
1030 if(NULL == wlanRxpFilterParam)
1031 {
1032 hddLog(VOS_TRACE_LEVEL_FATAL,
1033 "%s: vos_mem_alloc failed ", __func__);
1034 return;
1035 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001036 hddLog(VOS_TRACE_LEVEL_INFO,
1037 "%s: Configuring Mcast/Bcast Filter Setting. setfilter %d", __func__, setfilter);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301038 if (TRUE == setfilter)
1039 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301040 hdd_mcbc_filter_modification(pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301041 &wlanRxpFilterParam->configuredMcstBcstFilterSetting);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301042 }
1043 else
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301044 {
1045 /*Use the current configured value to clear*/
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301046 wlanRxpFilterParam->configuredMcstBcstFilterSetting =
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301047 pHddCtx->configuredMcastBcastFilter;
1048 }
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301049
Jeff Johnson295189b2012-06-20 16:38:30 -07001050 wlanRxpFilterParam->setMcstBcstFilter = setfilter;
Jeff Johnson295189b2012-06-20 16:38:30 -07001051 halStatus = sme_ConfigureRxpFilter(pHddCtx->hHal, wlanRxpFilterParam);
Chilam Ngc4244af2013-04-01 15:37:32 -07001052 if (eHAL_STATUS_SUCCESS != halStatus)
1053 vos_mem_free(wlanRxpFilterParam);
Jeff Johnson295189b2012-06-20 16:38:30 -07001054 if(setfilter && (eHAL_STATUS_SUCCESS == halStatus))
1055 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
1056}
1057
Jeff Johnson295189b2012-06-20 16:38:30 -07001058static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx,
1059 hdd_adapter_t *pAdapter)
1060{
1061 eHalStatus halStatus = eHAL_STATUS_FAILURE;
1062 tpSirWlanSuspendParam wlanSuspendParam =
1063 vos_mem_malloc(sizeof(tSirWlanSuspendParam));
1064
Amar Singhald53568e2013-09-26 11:03:45 -07001065 if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid) {
1066 pHddCtx->sus_res_mcastbcast_filter =
1067 pHddCtx->configuredMcastBcastFilter;
1068 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
1069 hddLog(VOS_TRACE_LEVEL_INFO, "offload: hdd_conf_suspend_ind");
1070 hddLog(VOS_TRACE_LEVEL_INFO, "configuredMCastBcastFilter saved = %d",
1071 pHddCtx->configuredMcastBcastFilter);
1072
1073 }
1074
Amar Singhal49fdfd52013-08-13 13:25:12 -07001075
Jeff Johnson295189b2012-06-20 16:38:30 -07001076 if(NULL == wlanSuspendParam)
1077 {
1078 hddLog(VOS_TRACE_LEVEL_FATAL,
1079 "%s: vos_mem_alloc failed ", __func__);
1080 return;
1081 }
1082
Amar Singhald53568e2013-09-26 11:03:45 -07001083 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001084 "%s: send wlan suspend indication", __func__);
1085
1086 if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER))
1087 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301088 //Configure supported OffLoads
1089 hdd_conf_hostoffload(pAdapter, TRUE);
1090 wlanSuspendParam->configuredMcstBcstFilterSetting = pHddCtx->configuredMcastBcastFilter;
Jeff Johnson295189b2012-06-20 16:38:30 -07001091
1092#ifdef WLAN_FEATURE_PACKET_FILTERING
madan mohan koyyalamudibfd9cef2013-07-01 18:39:37 +05301093 /* During suspend, configure MC Addr list filter to the firmware
1094 * function takes care of checking necessary conditions before
1095 * configuring.
1096 */
1097 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001098#endif
1099 }
1100
1101 halStatus = sme_ConfigureSuspendInd(pHddCtx->hHal, wlanSuspendParam);
1102 if(eHAL_STATUS_SUCCESS == halStatus)
1103 {
1104 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
Chilam Ngc4244af2013-04-01 15:37:32 -07001105 } else {
1106 vos_mem_free(wlanSuspendParam);
Jeff Johnson295189b2012-06-20 16:38:30 -07001107 }
1108}
1109
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301110static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001111{
Chilam Ngc4244af2013-04-01 15:37:32 -07001112 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Yathish9f22e662012-12-10 14:21:35 -08001113 hdd_context_t* pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Chilam Ngc4244af2013-04-01 15:37:32 -07001114 tpSirWlanResumeParam wlanResumeParam;
Jeff Johnson295189b2012-06-20 16:38:30 -07001115
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301116 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001117 "%s: send wlan resume indication", __func__);
1118
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301119 wlanResumeParam = vos_mem_malloc(sizeof(tSirWlanResumeParam));
1120
1121 if (NULL == wlanResumeParam)
Jeff Johnson295189b2012-06-20 16:38:30 -07001122 {
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301123 hddLog(VOS_TRACE_LEVEL_FATAL,
1124 "%s: memory allocation failed for wlanResumeParam ", __func__);
1125 return;
Jeff Johnson295189b2012-06-20 16:38:30 -07001126 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001127
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301128 //Disable supported OffLoads
1129 hdd_conf_hostoffload(pAdapter, FALSE);
1130
1131 wlanResumeParam->configuredMcstBcstFilterSetting =
1132 pHddCtx->configuredMcastBcastFilter;
1133 halStatus = sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam);
1134 if (eHAL_STATUS_SUCCESS != halStatus)
1135 {
1136 vos_mem_free(wlanResumeParam);
1137 }
1138
1139 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
1140
Amar Singhalf8ba2b82013-12-02 12:54:38 -08001141 if (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid) {
1142 pHddCtx->configuredMcastBcastFilter =
1143 pHddCtx->sus_res_mcastbcast_filter;
1144 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_FALSE;
1145 }
Amar Singhald53568e2013-09-26 11:03:45 -07001146
1147 hddLog(VOS_TRACE_LEVEL_INFO,
1148 "offload: in hdd_conf_resume_ind, restoring configuredMcastBcastFilter");
1149 hddLog(VOS_TRACE_LEVEL_INFO, "configuredMcastBcastFilter = %d",
1150 pHddCtx->configuredMcastBcastFilter);
Amar Singhal49fdfd52013-08-13 13:25:12 -07001151
Chilam Ngc4244af2013-04-01 15:37:32 -07001152
madan mohan koyyalamudibfd9cef2013-07-01 18:39:37 +05301153#ifdef WLAN_FEATURE_PACKET_FILTERING
1154 /* Filer was applied during suspend inditication
1155 * clear it when we resume.
1156 */
1157 wlan_hdd_set_mc_addr_list(pAdapter, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001158#endif
1159}
Jeff Johnson295189b2012-06-20 16:38:30 -07001160
Jeff Johnson295189b2012-06-20 16:38:30 -07001161//Suspend routine registered with Android OS
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001162void hdd_suspend_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001163{
1164 hdd_context_t *pHddCtx = NULL;
1165 v_CONTEXT_t pVosContext = NULL;
1166
Jeff Johnson295189b2012-06-20 16:38:30 -07001167 VOS_STATUS status;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301168 hdd_adapter_t *pAdapter = NULL;
1169 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301170 bool hdd_enter_bmps = FALSE;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001171
Jeff Johnson295189b2012-06-20 16:38:30 -07001172 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__);
1173
1174 //Get the global VOSS context.
1175 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1176 if(!pVosContext) {
1177 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1178 return;
1179 }
1180
1181 //Get the HDD context.
1182 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1183
1184 if(!pHddCtx) {
1185 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1186 return;
1187 }
1188
1189 if (pHddCtx->isLogpInProgress) {
1190 hddLog(VOS_TRACE_LEVEL_ERROR,
1191 "%s: Ignore suspend wlan, LOGP in progress!", __func__);
1192 return;
1193 }
1194
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301195 hdd_set_pwrparams(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001196 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1197 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1198 {
1199 pAdapter = pAdapterNode->pAdapter;
1200 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001201 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001202 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
1203
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001204 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001205 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1206 pAdapterNode = pNext;
1207 continue;
1208 }
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301209 /* Avoid multiple enter/exit BMPS in this while loop using
1210 * hdd_enter_bmps flag
1211 */
1212 if (FALSE == hdd_enter_bmps && (BMPS == pmcGetPmcState(pHddCtx->hHal)))
1213 {
1214 hdd_enter_bmps = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001215
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301216 /* If device was already in BMPS, and dynamic DTIM is set,
1217 * exit(set the device to full power) and enter BMPS again
1218 * to reflect new DTIM value */
1219 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
1220
1221 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
1222
1223 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1224 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001225#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1226 if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1227 {
1228 //stop the interface before putting the chip to standby
1229 netif_tx_disable(pAdapter->dev);
1230 netif_carrier_off(pAdapter->dev);
1231 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301232 else if (pHddCtx->cfg_ini->nEnableSuspend ==
Jeff Johnson295189b2012-06-20 16:38:30 -07001233 WLAN_MAP_SUSPEND_TO_DEEP_SLEEP)
1234 {
1235 //Execute deep sleep procedure
1236 hdd_enter_deep_sleep(pHddCtx, pAdapter);
1237 }
1238#endif
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301239
1240 /*Suspend notification sent down to driver*/
1241 hdd_conf_suspend_ind(pHddCtx, pAdapter);
1242
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301243 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1244 pAdapterNode = pNext;
1245 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301246 pHddCtx->hdd_wlan_suspended = TRUE;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301247
Jeff Johnson295189b2012-06-20 16:38:30 -07001248#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1249 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1250 {
1251 hdd_enter_standby(pHddCtx);
1252 }
1253#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001254
1255 return;
1256}
1257
1258static void hdd_PowerStateChangedCB
1259(
1260 v_PVOID_t callbackContext,
1261 tPmcState newState
1262)
1263{
1264 hdd_context_t *pHddCtx = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07001265 /* if the driver was not in BMPS during early suspend,
1266 * the dynamic DTIM is now updated at Riva */
1267 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended
1268 && pHddCtx->cfg_ini->enableDynamicDTIM
1269 && (pHddCtx->hdd_ignore_dtim_enabled == FALSE))
1270 {
1271 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1272 }
1273 spin_lock(&pHddCtx->filter_lock);
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301274 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended)
1275 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001276 spin_unlock(&pHddCtx->filter_lock);
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301277 if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid)
1278 {
Amar Singhald53568e2013-09-26 11:03:45 -07001279 pHddCtx->sus_res_mcastbcast_filter =
1280 pHddCtx->configuredMcastBcastFilter;
1281 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
1282
1283 hddLog(VOS_TRACE_LEVEL_INFO, "offload: callback to associated");
1284 hddLog(VOS_TRACE_LEVEL_INFO, "saving configuredMcastBcastFilter = %d",
1285 pHddCtx->configuredMcastBcastFilter);
1286 hddLog(VOS_TRACE_LEVEL_INFO,
1287 "offload: calling hdd_conf_mcastbcast_filter");
1288
1289 }
1290
Jeff Johnson295189b2012-06-20 16:38:30 -07001291 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001292 if(pHddCtx->hdd_mcastbcast_filter_set != TRUE)
1293 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__);
1294 }
Amar Singhal49fdfd52013-08-13 13:25:12 -07001295 else
Mihir Shete793209f2014-01-06 11:01:12 +05301296 {
1297 /* Android framework can send resume request when the WCN chip is
1298 * in IMPS mode. When the chip exits IMPS mode the firmware will
1299 * restore all the registers to the state they were before the chip
1300 * entered IMPS and so our hardware filter settings confgured by the
1301 * resume request will be lost. So reconfigure the filters on detecting
1302 * a change in the power state of the WCN chip.
1303 */
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301304 spin_unlock(&pHddCtx->filter_lock);
Mihir Shete793209f2014-01-06 11:01:12 +05301305 if (IMPS != newState)
1306 {
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301307 spin_lock(&pHddCtx->filter_lock);
Mihir Shete793209f2014-01-06 11:01:12 +05301308 if (FALSE == pHddCtx->hdd_wlan_suspended)
1309 {
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301310 spin_unlock(&pHddCtx->filter_lock);
Mihir Shete793209f2014-01-06 11:01:12 +05301311 hddLog(VOS_TRACE_LEVEL_INFO,
1312 "Not in IMPS/BMPS and suspended state");
1313 hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
1314 }
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301315 else
1316 {
1317 spin_unlock(&pHddCtx->filter_lock);
1318 }
Mihir Shete793209f2014-01-06 11:01:12 +05301319 }
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301320 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001321}
1322
1323
1324
1325void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx)
1326{
1327 v_CONTEXT_t pVosContext;
1328 tHalHandle smeContext;
1329
1330 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1331 if (NULL == pVosContext)
1332 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001333 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001334 return;
1335 }
1336 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1337 if (NULL == smeContext)
1338 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001339 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001340 return;
1341 }
1342
1343 spin_lock_init(&pHddCtx->filter_lock);
1344 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1345 pHddCtx->cfg_ini->nEnableSuspend)
1346 {
1347 pmcRegisterDeviceStateUpdateInd(smeContext,
1348 hdd_PowerStateChangedCB, pHddCtx);
1349 }
1350}
1351
1352void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx)
1353{
1354 v_CONTEXT_t pVosContext;
1355 tHalHandle smeContext;
1356
1357 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1358 if (NULL == pVosContext)
1359 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001360 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001361 return;
1362 }
1363 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1364 if (NULL == smeContext)
1365 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001366 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001367 return;
1368 }
1369
1370 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1371 pHddCtx->cfg_ini->nEnableSuspend)
1372 {
1373 pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB);
1374 }
1375}
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301376
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301377#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301378void hdd_conf_gtk_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301379{
1380 eHalStatus ret;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301381 tSirGtkOffloadParams hddGtkOffloadReqParams;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301382 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1383
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301384 if(fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301385 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301386 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1387 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags ))
1388 {
1389 vos_mem_copy(&hddGtkOffloadReqParams,
1390 &pHddStaCtx->gtkOffloadReqParams,
1391 sizeof (tSirGtkOffloadParams));
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301392
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301393 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1394 &hddGtkOffloadReqParams, pAdapter->sessionId);
1395 if (eHAL_STATUS_SUCCESS != ret)
1396 {
1397 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1398 "%s: sme_SetGTKOffload failed, returned %d",
1399 __func__, ret);
1400 return;
1401 }
1402
1403 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1404 "%s: sme_SetGTKOffload successfull", __func__);
1405 }
1406
1407 }
1408 else
1409 {
1410 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1411 (0 == memcmp(&pHddStaCtx->gtkOffloadReqParams.bssId,
1412 &pHddStaCtx->conn_info.bssId, WNI_CFG_BSSID_LEN)) &&
1413 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags))
1414 {
1415
1416 /* Host driver has previously offloaded GTK rekey */
1417 ret = sme_GetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301418 wlan_hdd_cfg80211_update_replayCounterCallback,
1419 pAdapter, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301420 if (eHAL_STATUS_SUCCESS != ret)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301421
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301422 {
1423 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1424 "%s: sme_GetGTKOffload failed, returned %d",
1425 __func__, ret);
1426 return;
1427 }
1428 else
1429 {
1430 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1431 "%s: sme_GetGTKOffload successful",
1432 __func__);
1433
1434 /* Sending GTK offload dissable */
1435 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
1436 sizeof (tSirGtkOffloadParams));
1437 hddGtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE;
1438 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301439 &hddGtkOffloadReqParams, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301440 if (eHAL_STATUS_SUCCESS != ret)
1441 {
1442 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1443 "%s: failed to dissable GTK offload, returned %d",
1444 __func__, ret);
1445 return;
1446 }
1447 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1448 "%s: successfully dissabled GTK offload request to HAL",
1449 __func__);
1450 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301451 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301452 }
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301453 return;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301454}
1455#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
Jeff Johnson295189b2012-06-20 16:38:30 -07001456
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001457void hdd_resume_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001458{
1459 hdd_context_t *pHddCtx = NULL;
1460 hdd_adapter_t *pAdapter = NULL;
1461 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1462 VOS_STATUS status;
1463 v_CONTEXT_t pVosContext = NULL;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001464
Jeff Johnson295189b2012-06-20 16:38:30 -07001465 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
1466
1467 //Get the global VOSS context.
1468 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1469 if(!pVosContext) {
1470 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1471 return;
1472 }
1473
1474 //Get the HDD context.
1475 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1476
1477 if(!pHddCtx) {
1478 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1479 return;
1480 }
1481
1482 if (pHddCtx->isLogpInProgress) {
1483 hddLog(VOS_TRACE_LEVEL_INFO,
1484 "%s: Ignore resume wlan, LOGP in progress!", __func__);
1485 return;
1486 }
1487
Jeff Johnson295189b2012-06-20 16:38:30 -07001488 pHddCtx->hdd_wlan_suspended = FALSE;
1489 /*loop through all adapters. Concurrency */
1490 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1491
1492 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1493 {
1494 pAdapter = pAdapterNode->pAdapter;
1495 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001496 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001497 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001498 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001499 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1500 pAdapterNode = pNext;
1501 continue;
1502 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301503
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301504
Jeff Johnson295189b2012-06-20 16:38:30 -07001505#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1506 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP)
1507 {
1508 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__);
1509 hdd_exit_deep_sleep(pAdapter);
1510 }
1511#endif
1512
1513 if(pHddCtx->hdd_ignore_dtim_enabled == TRUE)
1514 {
1515 /*Switch back to DTIM 1*/
1516 tSirSetPowerParamsReq powerRequest = { 0 };
1517
1518 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
1519 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07001520 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001521
1522 /*Disabled ModulatedDTIM if enabled on suspend*/
1523 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1524 powerRequest.uDTIMPeriod = 0;
1525
1526 /* Update ignoreDTIM and ListedInterval in CFG with default values */
1527 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1528 NULL, eANI_BOOLEAN_FALSE);
1529 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1530 NULL, eANI_BOOLEAN_FALSE);
1531
1532 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001533 "Switch to DTIM%d",powerRequest.uListenInterval);
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08001534 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001535
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301536 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
1537 {
1538 /* put the device into full power */
1539 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001540
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301541 /* put the device back into BMPS */
1542 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
Jeff Johnson295189b2012-06-20 16:38:30 -07001543
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301544 pHddCtx->hdd_ignore_dtim_enabled = FALSE;
1545 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001546 }
1547
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301548 hdd_conf_resume_ind(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001549 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1550 pAdapterNode = pNext;
1551 }
1552
1553#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1554 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY)
1555 {
1556 hdd_exit_standby(pHddCtx);
1557 }
1558#endif
1559
Jeff Johnson295189b2012-06-20 16:38:30 -07001560 return;
1561}
1562
Jeff Johnson295189b2012-06-20 16:38:30 -07001563VOS_STATUS hdd_wlan_reset_initialization(void)
1564{
Jeff Johnson295189b2012-06-20 16:38:30 -07001565 v_CONTEXT_t pVosContext = NULL;
1566
1567 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1568
1569 //Get the global VOSS context.
1570 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1571 if(!pVosContext)
1572 {
1573 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1574 return VOS_STATUS_E_FAILURE;
1575 }
1576
1577 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__);
1578
1579 // Prevent the phone from going to sleep
1580 hdd_prevent_suspend();
1581
Jeff Johnson295189b2012-06-20 16:38:30 -07001582 return VOS_STATUS_SUCCESS;
1583}
1584
1585
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001586/*
1587 * Based on the ioctl command recieved by HDD, put WLAN driver
1588 * into the quiet mode. This is the same as the early suspend
1589 * notification that driver used to listen
1590 */
1591void hdd_set_wlan_suspend_mode(bool suspend)
Jeff Johnson295189b2012-06-20 16:38:30 -07001592{
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001593 if (suspend)
1594 hdd_suspend_wlan();
1595 else
1596 hdd_resume_wlan();
Jeff Johnson295189b2012-06-20 16:38:30 -07001597}
1598
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001599static void hdd_ssr_timer_init(void)
1600{
1601 init_timer(&ssr_timer);
1602}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001603
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001604static void hdd_ssr_timer_del(void)
1605{
1606 del_timer(&ssr_timer);
1607 ssr_timer_started = false;
1608}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001609
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001610static void hdd_ssr_timer_cb(unsigned long data)
1611{
1612 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD SSR timer expired", __func__);
Sameer Thalappile5637f42013-08-07 15:46:55 -07001613
1614#ifdef WCN_PRONTO
1615 if (wcnss_hardware_type() == WCNSS_PRONTO_HW)
1616 wcnss_pronto_log_debug_regs();
1617#endif
1618
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001619 VOS_BUG(0);
1620}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001621
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001622static void hdd_ssr_timer_start(int msec)
1623{
1624 if(ssr_timer_started)
1625 {
1626 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: trying to start SSR timer when it's running"
1627 ,__func__);
1628 }
1629 ssr_timer.expires = jiffies + msecs_to_jiffies(msec);
1630 ssr_timer.function = hdd_ssr_timer_cb;
1631 add_timer(&ssr_timer);
1632 ssr_timer_started = true;
1633}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001634
Jeff Johnson295189b2012-06-20 16:38:30 -07001635/* the HDD interface to WLAN driver shutdown,
1636 * the primary shutdown function in SSR
1637 */
1638VOS_STATUS hdd_wlan_shutdown(void)
1639{
1640 VOS_STATUS vosStatus;
1641 v_CONTEXT_t pVosContext = NULL;
1642 hdd_context_t *pHddCtx = NULL;
1643 pVosSchedContext vosSchedContext = NULL;
1644
1645 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__);
1646
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001647 /* if re-init never happens, then do SSR1 */
1648 hdd_ssr_timer_init();
1649 hdd_ssr_timer_start(HDD_SSR_BRING_UP_TIME);
1650
Jeff Johnson295189b2012-06-20 16:38:30 -07001651 /* Get the global VOSS context. */
1652 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1653 if(!pVosContext) {
1654 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1655 return VOS_STATUS_E_FAILURE;
1656 }
1657 /* Get the HDD context. */
1658 pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1659 if(!pHddCtx) {
1660 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1661 return VOS_STATUS_E_FAILURE;
1662 }
c_hpothud662a352013-12-26 15:09:12 +05301663
1664 //Stop the traffic monitor timer
1665 if ( VOS_TIMER_STATE_RUNNING ==
1666 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
1667 {
1668 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
1669 }
1670
Jeff Johnson295189b2012-06-20 16:38:30 -07001671 hdd_reset_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001672 /* DeRegister with platform driver as client for Suspend/Resume */
1673 vosStatus = hddDeregisterPmOps(pHddCtx);
1674 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1675 {
1676 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
1677 }
1678
1679 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
1680 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1681 {
1682 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
1683 }
1684
1685 /* Disable IMPS/BMPS as we do not want the device to enter any power
1686 * save mode on its own during reset sequence
1687 */
1688 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1689 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1690 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1691
1692 vosSchedContext = get_vos_sched_ctxt();
1693
1694 /* Wakeup all driver threads */
1695 if(TRUE == pHddCtx->isMcThreadSuspended){
1696 complete(&vosSchedContext->ResumeMcEvent);
1697 pHddCtx->isMcThreadSuspended= FALSE;
1698 }
1699 if(TRUE == pHddCtx->isTxThreadSuspended){
1700 complete(&vosSchedContext->ResumeTxEvent);
1701 pHddCtx->isTxThreadSuspended= FALSE;
1702 }
1703 if(TRUE == pHddCtx->isRxThreadSuspended){
1704 complete(&vosSchedContext->ResumeRxEvent);
1705 pHddCtx->isRxThreadSuspended= FALSE;
1706 }
1707 /* Reset the Suspend Variable */
1708 pHddCtx->isWlanSuspended = FALSE;
1709
1710 /* Stop all the threads; we do not want any messages to be a processed,
1711 * any more and the best way to ensure that is to terminate the threads
1712 * gracefully.
1713 */
1714 /* Wait for MC to exit */
1715 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
1716 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
1717 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
1718 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
Mihir Shete165143a2013-12-19 09:06:13 +05301719 wait_for_completion(&vosSchedContext->McShutdown);
Jeff Johnson295189b2012-06-20 16:38:30 -07001720
1721 /* Wait for TX to exit */
1722 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
1723 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
1724 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
1725 wake_up_interruptible(&vosSchedContext->txWaitQueue);
Mihir Shete165143a2013-12-19 09:06:13 +05301726 wait_for_completion(&vosSchedContext->TxShutdown);
Jeff Johnson295189b2012-06-20 16:38:30 -07001727
1728 /* Wait for RX to exit */
1729 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
1730 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
1731 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
1732 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
Mihir Shete165143a2013-12-19 09:06:13 +05301733 wait_for_completion(&vosSchedContext->RxShutdown);
Jeff Johnson295189b2012-06-20 16:38:30 -07001734
1735#ifdef WLAN_BTAMP_FEATURE
1736 vosStatus = WLANBAP_Stop(pVosContext);
1737 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1738 {
1739 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1740 "%s: Failed to stop BAP",__func__);
1741 }
1742#endif //WLAN_BTAMP_FEATURE
1743 vosStatus = vos_wda_shutdown(pVosContext);
1744 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1745
1746 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
1747 /* Stop SME - Cannot invoke vos_stop as vos_stop relies
1748 * on threads being running to process the SYS Stop
1749 */
Kiet Lama72a2322013-11-15 11:18:11 +05301750 vosStatus = sme_Stop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
Jeff Johnson295189b2012-06-20 16:38:30 -07001751 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1752
1753 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
1754 /* Stop MAC (PE and HAL) */
1755 vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
1756 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1757
1758 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
1759 /* Stop TL */
1760 vosStatus = WLANTL_Stop(pVosContext);
1761 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1762
Jeff Johnson295189b2012-06-20 16:38:30 -07001763 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001764 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__);
1765 /* Clean up message queues of TX and MC thread */
1766 vos_sched_flush_mc_mqs(vosSchedContext);
1767 vos_sched_flush_tx_mqs(vosSchedContext);
1768 vos_sched_flush_rx_mqs(vosSchedContext);
1769
1770 /* Deinit all the TX and MC queues */
1771 vos_sched_deinit_mqs(vosSchedContext);
1772 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__);
1773
1774 /* shutdown VOSS */
1775 vos_shutdown(pVosContext);
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05301776
1777 /*mac context has already been released in mac_close call
1778 so setting it to NULL in hdd context*/
1779 pHddCtx->hHal = (tHalHandle)NULL;
1780
Jeff Johnson295189b2012-06-20 16:38:30 -07001781 if (free_riva_power_on_lock("wlan"))
1782 {
1783 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
1784 __func__);
1785 }
1786 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete"
1787 ,__func__);
1788 return VOS_STATUS_SUCCESS;
1789}
1790
1791
1792
1793/* the HDD interface to WLAN driver re-init.
1794 * This is called to initialize/start WLAN driver after a shutdown.
1795 */
1796VOS_STATUS hdd_wlan_re_init(void)
1797{
1798 VOS_STATUS vosStatus;
1799 v_CONTEXT_t pVosContext = NULL;
1800 hdd_context_t *pHddCtx = NULL;
1801 eHalStatus halStatus;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07001802#ifdef HAVE_WCNSS_CAL_DOWNLOAD
1803 int max_retries = 0;
1804#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001805#ifdef WLAN_BTAMP_FEATURE
1806 hdd_config_t *pConfig = NULL;
1807 WLANBAP_ConfigType btAmpConfig;
1808#endif
1809
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001810 hdd_ssr_timer_del();
Jeff Johnson295189b2012-06-20 16:38:30 -07001811 hdd_prevent_suspend();
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001812
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07001813#ifdef HAVE_WCNSS_CAL_DOWNLOAD
1814 /* wait until WCNSS driver downloads NV */
1815 while (!wcnss_device_ready() && 5 >= ++max_retries) {
1816 msleep(1000);
1817 }
1818 if (max_retries >= 5) {
1819 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
1820 goto err_re_init;
1821 }
1822#endif
1823
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07001824 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, TRUE);
1825
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001826 /* The driver should always be initialized in STA mode after SSR */
1827 hdd_set_conparam(0);
1828
Jeff Johnson295189b2012-06-20 16:38:30 -07001829 /* Re-open VOSS, it is a re-open b'se control transport was never closed. */
1830 vosStatus = vos_open(&pVosContext, 0);
1831 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1832 {
1833 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
1834 goto err_re_init;
1835 }
1836
1837 /* Get the HDD context. */
1838 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1839 if(!pHddCtx)
1840 {
1841 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1842 goto err_vosclose;
1843 }
1844
1845 /* Save the hal context in Adapter */
1846 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
1847 if ( NULL == pHddCtx->hHal )
1848 {
1849 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
1850 goto err_vosclose;
1851 }
1852
1853 /* Set the SME configuration parameters. */
1854 vosStatus = hdd_set_sme_config(pHddCtx);
1855 if ( VOS_STATUS_SUCCESS != vosStatus )
1856 {
1857 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
1858 goto err_vosclose;
1859 }
1860
1861 /* Initialize the WMM module */
1862 vosStatus = hdd_wmm_init(pHddCtx);
1863 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
1864 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001865 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001866 goto err_vosclose;
1867 }
1868
1869 vosStatus = vos_preStart( pHddCtx->pvosContext );
1870 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1871 {
1872 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
1873 goto err_vosclose;
1874 }
1875
1876 /* In the integrated architecture we update the configuration from
1877 the INI file and from NV before vOSS has been started so that
1878 the final contents are available to send down to the cCPU */
1879 /* Apply the cfg.ini to cfg.dat */
1880 if (FALSE == hdd_update_config_dat(pHddCtx))
1881 {
1882 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
1883 goto err_vosclose;
1884 }
1885
1886 /* Set the MAC Address, currently this is used by HAL to add self sta.
1887 * Remove this once self sta is added as part of session open. */
1888 halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID,
1889 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
1890 sizeof(pHddCtx->cfg_ini->intfMacAddr[0]));
1891 if (!HAL_STATUS_SUCCESS(halStatus))
1892 {
1893 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
1894 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus);
1895 goto err_vosclose;
1896 }
1897
1898 /* Start VOSS which starts up the SME/MAC/HAL modules and everything else
1899 Note: Firmware image will be read and downloaded inside vos_start API */
1900 vosStatus = vos_start( pVosContext );
1901 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1902 {
1903 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
1904 goto err_vosclose;
1905 }
1906
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07001907 /* Exchange capability info between Host and FW and also get versioning info from FW */
1908 hdd_exchange_version_and_caps(pHddCtx);
1909
Jeff Johnson295189b2012-06-20 16:38:30 -07001910 vosStatus = hdd_post_voss_start_config( pHddCtx );
1911 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1912 {
1913 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
1914 __func__);
1915 goto err_vosstop;
1916 }
1917
1918#ifdef WLAN_BTAMP_FEATURE
1919 vosStatus = WLANBAP_Open(pVosContext);
1920 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1921 {
1922 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1923 "%s: Failed to open BAP",__func__);
1924 goto err_vosstop;
1925 }
1926 vosStatus = BSL_Init(pVosContext);
1927 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1928 {
1929 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1930 "%s: Failed to Init BSL",__func__);
1931 goto err_bap_close;
1932 }
1933 vosStatus = WLANBAP_Start(pVosContext);
1934 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1935 {
1936 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1937 "%s: Failed to start TL",__func__);
1938 goto err_bap_close;
1939 }
1940 pConfig = pHddCtx->cfg_ini;
1941 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
1942 vosStatus = WLANBAP_SetConfig(&btAmpConfig);
1943#endif //WLAN_BTAMP_FEATURE
1944
1945 /* Restart all adapters */
1946 hdd_start_all_adapters(pHddCtx);
1947 pHddCtx->isLogpInProgress = FALSE;
Sameer Thalappilb511beb2013-09-09 17:11:51 -07001948 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001949 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001950 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001951
1952 /* Register with platform driver as client for Suspend/Resume */
1953 vosStatus = hddRegisterPmOps(pHddCtx);
1954 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1955 {
1956 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
1957 goto err_bap_stop;
1958 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001959 /* Allow the phone to go to sleep */
1960 hdd_allow_suspend();
1961 /* register for riva power on lock */
1962 if (req_riva_power_on_lock("wlan"))
1963 {
1964 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
1965 __func__);
1966 goto err_unregister_pmops;
1967 }
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07001968 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001969 goto success;
1970
1971err_unregister_pmops:
1972 hddDeregisterPmOps(pHddCtx);
1973
1974err_bap_stop:
Jeff Johnson32d95a32012-09-10 13:15:23 -07001975#ifdef CONFIG_HAS_EARLYSUSPEND
1976 hdd_unregister_mcast_bcast_filter(pHddCtx);
1977#endif
1978 hdd_close_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001979#ifdef WLAN_BTAMP_FEATURE
Jeff Johnson32d95a32012-09-10 13:15:23 -07001980 WLANBAP_Stop(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07001981#endif
1982
1983#ifdef WLAN_BTAMP_FEATURE
1984err_bap_close:
1985 WLANBAP_Close(pVosContext);
1986#endif
1987
1988err_vosstop:
1989 vos_stop(pVosContext);
1990
1991err_vosclose:
1992 vos_close(pVosContext);
1993 vos_sched_close(pVosContext);
1994 if (pHddCtx)
1995 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001996 /* Unregister the Net Device Notifier */
1997 unregister_netdevice_notifier(&hdd_netdev_notifier);
1998 /* Clean up HDD Nlink Service */
1999 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07002000#ifdef WLAN_KD_READY_NOTIFIER
2001 nl_srv_exit(pHddCtx->ptt_pid);
2002#else
Jeff Johnson295189b2012-06-20 16:38:30 -07002003 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07002004#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07002005 /* Free up dynamically allocated members inside HDD Adapter */
2006 kfree(pHddCtx->cfg_ini);
2007 pHddCtx->cfg_ini= NULL;
2008
Jeff Johnson295189b2012-06-20 16:38:30 -07002009 wiphy_unregister(pHddCtx->wiphy);
2010 wiphy_free(pHddCtx->wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07002011 }
2012 vos_preClose(&pVosContext);
2013
2014#ifdef MEMORY_DEBUG
2015 vos_mem_exit();
2016#endif
2017
2018err_re_init:
2019 /* Allow the phone to go to sleep */
2020 hdd_allow_suspend();
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07002021 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07002022 VOS_BUG(0);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002023 return -EPERM;
Jeff Johnson295189b2012-06-20 16:38:30 -07002024
2025success:
2026 /* Trigger replay of BTC events */
2027 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
2028 return VOS_STATUS_SUCCESS;
2029}