blob: e71460fb3b09e1cc3b1465caef14ff3d289cb3c8 [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);
823
824 if (pAdapter && pAdapter->dev == ndev)
825 {
826 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
827 {
828 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
829 ifap = &ifa->ifa_next)
830 {
831 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
832 {
833 break; /* found */
834 }
835 }
836 }
837 if(ifa && ifa->ifa_local)
838 {
839 schedule_work(&pAdapter->ipv4NotifierWorkQueue);
840 }
841 }
842
843 return NOTIFY_DONE;
844}
845
846/**----------------------------------------------------------------------------
847
848 \brief hdd_conf_arp_offload() - Configure ARP offload
849
850 Called during SUSPEND to configure the ARP offload (MC BC filter) which
851 reduces power consumption.
852
853 \param - pAdapter -Adapter context for which ARP offload is to be configured
854 \param - fenable - 0 - disable.
855 1 - enable. (with IPv4 notifier registration)
856 2 - enable. (without IPv4 notifier registration)
857
858 \return -
859 VOS_STATUS_SUCCESS - on successful operation
860 VOS_STATUS_E_FAILURE - on failure of operation
861-----------------------------------------------------------------------------*/
862VOS_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, int fenable)
Jeff Johnson295189b2012-06-20 16:38:30 -0700863{
864 struct in_ifaddr **ifap = NULL;
865 struct in_ifaddr *ifa = NULL;
866 struct in_device *in_dev;
867 int i = 0;
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530868 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700869 tSirHostOffloadReq offLoadRequest;
Yathish9f22e662012-12-10 14:21:35 -0800870 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700871
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530872 hddLog(VOS_TRACE_LEVEL_ERROR, FL(" fenable = %d \n"), fenable);
Jeff Johnson295189b2012-06-20 16:38:30 -0700873
Jeff Johnson295189b2012-06-20 16:38:30 -0700874 if(fenable)
875 {
876 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
877 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530878 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700879 ifap = &ifa->ifa_next)
880 {
881 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
882 {
883 break; /* found */
884 }
885 }
886 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700887 if(ifa && ifa->ifa_local)
888 {
889 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
890 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
891
Arif Hussain6d2a3322013-11-17 19:50:10 -0800892 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700893
Amar Singhald53568e2013-09-26 11:03:45 -0700894 if (((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
895 pHddCtx->sus_res_mcastbcast_filter) ||
896 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
897 pHddCtx->sus_res_mcastbcast_filter)) &&
898 (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid))
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700899 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530900 offLoadRequest.enableOrDisable =
Amar Singhald53568e2013-09-26 11:03:45 -0700901 SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
902 hddLog(VOS_TRACE_LEVEL_INFO,
903 "offload: inside arp offload conditional check");
Jeff Johnson295189b2012-06-20 16:38:30 -0700904 }
Amar Singhald53568e2013-09-26 11:03:45 -0700905
906 hddLog(VOS_TRACE_LEVEL_INFO, "offload: arp filter programmed = %d",
907 offLoadRequest.enableOrDisable);
908
Jeff Johnson295189b2012-06-20 16:38:30 -0700909 //converting u32 to IPV4 address
910 for(i = 0 ; i < 4; i++)
911 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530912 offLoadRequest.params.hostIpv4Addr[i] =
Jeff Johnson295189b2012-06-20 16:38:30 -0700913 (ifa->ifa_local >> (i*8) ) & 0xFF ;
914 }
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530915 hddLog(VOS_TRACE_LEVEL_INFO, " Enable SME HostOffload: %d.%d.%d.%d",
Jeff Johnson295189b2012-06-20 16:38:30 -0700916 offLoadRequest.params.hostIpv4Addr[0],
917 offLoadRequest.params.hostIpv4Addr[1],
918 offLoadRequest.params.hostIpv4Addr[2],
919 offLoadRequest.params.hostIpv4Addr[3]);
920
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530921 if (eHAL_STATUS_SUCCESS !=
922 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
923 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700924 {
925 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to enable HostOffload "
Arif Hussain6d2a3322013-11-17 19:50:10 -0800926 "feature", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700927 return VOS_STATUS_E_FAILURE;
928 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700929 }
930 else
931 {
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530932 hddLog(VOS_TRACE_LEVEL_INFO, FL("IP Address is not assigned\n"));
Jeff Johnson295189b2012-06-20 16:38:30 -0700933 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530934
935 if (fenable == 1)
936 {
937 // Register IPv4 notifier to notify if any change in IP
938 // So that we can reconfigure the offload parameters
939 pAdapter->ipv4_notifier.notifier_call =
940 wlan_hdd_ipv4_changed;
941 ret = register_inetaddr_notifier(&pAdapter->ipv4_notifier);
942 if (ret)
943 {
944 hddLog(LOGE, FL("Failed to register IPv4 notifier"));
945 }
946 }
947 return VOS_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -0700948 }
949 else
950 {
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530951 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
Jeff Johnson295189b2012-06-20 16:38:30 -0700952 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
953 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
954 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
955
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530956 if (eHAL_STATUS_SUCCESS !=
957 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
958 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700959 {
960 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to disable host "
Arif Hussain6d2a3322013-11-17 19:50:10 -0800961 "offload feature", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700962 return VOS_STATUS_E_FAILURE;
963 }
964 return VOS_STATUS_SUCCESS;
965 }
966}
967
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530968/*
969 * This function is called before setting mcbc filters
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530970 * to modify filter value considering Different Offloads
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530971*/
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530972void hdd_mcbc_filter_modification(hdd_context_t* pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530973 tANI_U8 *pMcBcFilter)
974{
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530975 if (NULL == pHddCtx)
976 {
977 hddLog(VOS_TRACE_LEVEL_ERROR, FL("NULL HDD context passed"));
978 return;
979 }
980
981 *pMcBcFilter = pHddCtx->configuredMcastBcastFilter;
982 if (pHddCtx->cfg_ini->fhostArpOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530983 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530984 /* ARP offload is enabled, do not block bcast packets at RXP
985 * Will be using Bitmasking to reset the filter. As we have
986 * disable Broadcast filtering, Anding with the negation
987 * of Broadcast BIT
988 */
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530989 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530990 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530991
992#ifdef WLAN_NS_OFFLOAD
993 if (pHddCtx->cfg_ini->fhostNSOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530994 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530995 /* NS offload is enabled, do not block mcast packets at RXP
996 * Will be using Bitmasking to reset the filter. As we have
997 * disable Multicast filtering, Anding with the negation
998 * of Multicast BIT
999 */
1000 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301001 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301002#endif
1003
1004 pHddCtx->configuredMcastBcastFilter = *pMcBcFilter;
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301005}
1006
Jeff Johnson295189b2012-06-20 16:38:30 -07001007void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter)
1008{
1009 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001010 tpSirWlanSetRxpFilters wlanRxpFilterParam =
1011 vos_mem_malloc(sizeof(tSirWlanSetRxpFilters));
1012 if(NULL == wlanRxpFilterParam)
1013 {
1014 hddLog(VOS_TRACE_LEVEL_FATAL,
1015 "%s: vos_mem_alloc failed ", __func__);
1016 return;
1017 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001018 hddLog(VOS_TRACE_LEVEL_INFO,
1019 "%s: Configuring Mcast/Bcast Filter Setting. setfilter %d", __func__, setfilter);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301020 if (TRUE == setfilter)
1021 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301022 hdd_mcbc_filter_modification(pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301023 &wlanRxpFilterParam->configuredMcstBcstFilterSetting);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301024 }
1025 else
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301026 {
1027 /*Use the current configured value to clear*/
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301028 wlanRxpFilterParam->configuredMcstBcstFilterSetting =
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301029 pHddCtx->configuredMcastBcastFilter;
1030 }
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301031
Jeff Johnson295189b2012-06-20 16:38:30 -07001032 wlanRxpFilterParam->setMcstBcstFilter = setfilter;
Jeff Johnson295189b2012-06-20 16:38:30 -07001033 halStatus = sme_ConfigureRxpFilter(pHddCtx->hHal, wlanRxpFilterParam);
Chilam Ngc4244af2013-04-01 15:37:32 -07001034 if (eHAL_STATUS_SUCCESS != halStatus)
1035 vos_mem_free(wlanRxpFilterParam);
Jeff Johnson295189b2012-06-20 16:38:30 -07001036 if(setfilter && (eHAL_STATUS_SUCCESS == halStatus))
1037 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
1038}
1039
Jeff Johnson295189b2012-06-20 16:38:30 -07001040static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx,
1041 hdd_adapter_t *pAdapter)
1042{
1043 eHalStatus halStatus = eHAL_STATUS_FAILURE;
1044 tpSirWlanSuspendParam wlanSuspendParam =
1045 vos_mem_malloc(sizeof(tSirWlanSuspendParam));
1046
Amar Singhald53568e2013-09-26 11:03:45 -07001047 if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid) {
1048 pHddCtx->sus_res_mcastbcast_filter =
1049 pHddCtx->configuredMcastBcastFilter;
1050 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
1051 hddLog(VOS_TRACE_LEVEL_INFO, "offload: hdd_conf_suspend_ind");
1052 hddLog(VOS_TRACE_LEVEL_INFO, "configuredMCastBcastFilter saved = %d",
1053 pHddCtx->configuredMcastBcastFilter);
1054
1055 }
1056
Amar Singhal49fdfd52013-08-13 13:25:12 -07001057
Jeff Johnson295189b2012-06-20 16:38:30 -07001058 if(NULL == wlanSuspendParam)
1059 {
1060 hddLog(VOS_TRACE_LEVEL_FATAL,
1061 "%s: vos_mem_alloc failed ", __func__);
1062 return;
1063 }
1064
Amar Singhald53568e2013-09-26 11:03:45 -07001065 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001066 "%s: send wlan suspend indication", __func__);
1067
1068 if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER))
1069 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301070 //Configure supported OffLoads
1071 hdd_conf_hostoffload(pAdapter, TRUE);
1072 wlanSuspendParam->configuredMcstBcstFilterSetting = pHddCtx->configuredMcastBcastFilter;
Jeff Johnson295189b2012-06-20 16:38:30 -07001073
1074#ifdef WLAN_FEATURE_PACKET_FILTERING
madan mohan koyyalamudibfd9cef2013-07-01 18:39:37 +05301075 /* During suspend, configure MC Addr list filter to the firmware
1076 * function takes care of checking necessary conditions before
1077 * configuring.
1078 */
1079 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001080#endif
1081 }
1082
1083 halStatus = sme_ConfigureSuspendInd(pHddCtx->hHal, wlanSuspendParam);
1084 if(eHAL_STATUS_SUCCESS == halStatus)
1085 {
1086 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
Chilam Ngc4244af2013-04-01 15:37:32 -07001087 } else {
1088 vos_mem_free(wlanSuspendParam);
Jeff Johnson295189b2012-06-20 16:38:30 -07001089 }
1090}
1091
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301092static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001093{
Chilam Ngc4244af2013-04-01 15:37:32 -07001094 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Yathish9f22e662012-12-10 14:21:35 -08001095 hdd_context_t* pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Chilam Ngc4244af2013-04-01 15:37:32 -07001096 tpSirWlanResumeParam wlanResumeParam;
Jeff Johnson295189b2012-06-20 16:38:30 -07001097
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301098 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001099 "%s: send wlan resume indication", __func__);
1100
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301101 wlanResumeParam = vos_mem_malloc(sizeof(tSirWlanResumeParam));
1102
1103 if (NULL == wlanResumeParam)
Jeff Johnson295189b2012-06-20 16:38:30 -07001104 {
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301105 hddLog(VOS_TRACE_LEVEL_FATAL,
1106 "%s: memory allocation failed for wlanResumeParam ", __func__);
1107 return;
Jeff Johnson295189b2012-06-20 16:38:30 -07001108 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001109
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301110 //Disable supported OffLoads
1111 hdd_conf_hostoffload(pAdapter, FALSE);
1112
1113 wlanResumeParam->configuredMcstBcstFilterSetting =
1114 pHddCtx->configuredMcastBcastFilter;
1115 halStatus = sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam);
1116 if (eHAL_STATUS_SUCCESS != halStatus)
1117 {
1118 vos_mem_free(wlanResumeParam);
1119 }
1120
1121 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
1122
Amar Singhalf8ba2b82013-12-02 12:54:38 -08001123 if (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid) {
1124 pHddCtx->configuredMcastBcastFilter =
1125 pHddCtx->sus_res_mcastbcast_filter;
1126 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_FALSE;
1127 }
Amar Singhald53568e2013-09-26 11:03:45 -07001128
1129 hddLog(VOS_TRACE_LEVEL_INFO,
1130 "offload: in hdd_conf_resume_ind, restoring configuredMcastBcastFilter");
1131 hddLog(VOS_TRACE_LEVEL_INFO, "configuredMcastBcastFilter = %d",
1132 pHddCtx->configuredMcastBcastFilter);
Amar Singhal49fdfd52013-08-13 13:25:12 -07001133
Chilam Ngc4244af2013-04-01 15:37:32 -07001134
madan mohan koyyalamudibfd9cef2013-07-01 18:39:37 +05301135#ifdef WLAN_FEATURE_PACKET_FILTERING
1136 /* Filer was applied during suspend inditication
1137 * clear it when we resume.
1138 */
1139 wlan_hdd_set_mc_addr_list(pAdapter, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001140#endif
1141}
Jeff Johnson295189b2012-06-20 16:38:30 -07001142
Jeff Johnson295189b2012-06-20 16:38:30 -07001143//Suspend routine registered with Android OS
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001144void hdd_suspend_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001145{
1146 hdd_context_t *pHddCtx = NULL;
1147 v_CONTEXT_t pVosContext = NULL;
1148
Jeff Johnson295189b2012-06-20 16:38:30 -07001149 VOS_STATUS status;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301150 hdd_adapter_t *pAdapter = NULL;
1151 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301152 bool hdd_enter_bmps = FALSE;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001153
Jeff Johnson295189b2012-06-20 16:38:30 -07001154 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__);
1155
1156 //Get the global VOSS context.
1157 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1158 if(!pVosContext) {
1159 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1160 return;
1161 }
1162
1163 //Get the HDD context.
1164 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1165
1166 if(!pHddCtx) {
1167 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1168 return;
1169 }
1170
1171 if (pHddCtx->isLogpInProgress) {
1172 hddLog(VOS_TRACE_LEVEL_ERROR,
1173 "%s: Ignore suspend wlan, LOGP in progress!", __func__);
1174 return;
1175 }
1176
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301177 hdd_set_pwrparams(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001178 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1179 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1180 {
1181 pAdapter = pAdapterNode->pAdapter;
1182 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001183 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001184 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
1185
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001186 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001187 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1188 pAdapterNode = pNext;
1189 continue;
1190 }
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301191 /* Avoid multiple enter/exit BMPS in this while loop using
1192 * hdd_enter_bmps flag
1193 */
1194 if (FALSE == hdd_enter_bmps && (BMPS == pmcGetPmcState(pHddCtx->hHal)))
1195 {
1196 hdd_enter_bmps = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001197
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301198 /* If device was already in BMPS, and dynamic DTIM is set,
1199 * exit(set the device to full power) and enter BMPS again
1200 * to reflect new DTIM value */
1201 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
1202
1203 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
1204
1205 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1206 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001207#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1208 if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1209 {
1210 //stop the interface before putting the chip to standby
1211 netif_tx_disable(pAdapter->dev);
1212 netif_carrier_off(pAdapter->dev);
1213 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301214 else if (pHddCtx->cfg_ini->nEnableSuspend ==
Jeff Johnson295189b2012-06-20 16:38:30 -07001215 WLAN_MAP_SUSPEND_TO_DEEP_SLEEP)
1216 {
1217 //Execute deep sleep procedure
1218 hdd_enter_deep_sleep(pHddCtx, pAdapter);
1219 }
1220#endif
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301221
1222 /*Suspend notification sent down to driver*/
1223 hdd_conf_suspend_ind(pHddCtx, pAdapter);
1224
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301225 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1226 pAdapterNode = pNext;
1227 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301228 pHddCtx->hdd_wlan_suspended = TRUE;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301229
Jeff Johnson295189b2012-06-20 16:38:30 -07001230#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1231 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1232 {
1233 hdd_enter_standby(pHddCtx);
1234 }
1235#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001236
1237 return;
1238}
1239
1240static void hdd_PowerStateChangedCB
1241(
1242 v_PVOID_t callbackContext,
1243 tPmcState newState
1244)
1245{
1246 hdd_context_t *pHddCtx = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07001247 /* if the driver was not in BMPS during early suspend,
1248 * the dynamic DTIM is now updated at Riva */
1249 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended
1250 && pHddCtx->cfg_ini->enableDynamicDTIM
1251 && (pHddCtx->hdd_ignore_dtim_enabled == FALSE))
1252 {
1253 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1254 }
1255 spin_lock(&pHddCtx->filter_lock);
Gopichand Nakkalac1b11522013-03-25 15:25:33 +05301256 if((newState == BMPS) && pHddCtx->hdd_wlan_suspended) {
Jeff Johnson295189b2012-06-20 16:38:30 -07001257 spin_unlock(&pHddCtx->filter_lock);
Amar Singhald53568e2013-09-26 11:03:45 -07001258 if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid) {
1259 pHddCtx->sus_res_mcastbcast_filter =
1260 pHddCtx->configuredMcastBcastFilter;
1261 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
1262
1263 hddLog(VOS_TRACE_LEVEL_INFO, "offload: callback to associated");
1264 hddLog(VOS_TRACE_LEVEL_INFO, "saving configuredMcastBcastFilter = %d",
1265 pHddCtx->configuredMcastBcastFilter);
1266 hddLog(VOS_TRACE_LEVEL_INFO,
1267 "offload: calling hdd_conf_mcastbcast_filter");
1268
1269 }
1270
Jeff Johnson295189b2012-06-20 16:38:30 -07001271 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001272 if(pHddCtx->hdd_mcastbcast_filter_set != TRUE)
1273 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__);
1274 }
Amar Singhal49fdfd52013-08-13 13:25:12 -07001275 else
Mihir Shete793209f2014-01-06 11:01:12 +05301276 {
1277 /* Android framework can send resume request when the WCN chip is
1278 * in IMPS mode. When the chip exits IMPS mode the firmware will
1279 * restore all the registers to the state they were before the chip
1280 * entered IMPS and so our hardware filter settings confgured by the
1281 * resume request will be lost. So reconfigure the filters on detecting
1282 * a change in the power state of the WCN chip.
1283 */
1284 if (IMPS != newState)
1285 {
1286 if (FALSE == pHddCtx->hdd_wlan_suspended)
1287 {
1288 hddLog(VOS_TRACE_LEVEL_INFO,
1289 "Not in IMPS/BMPS and suspended state");
1290 hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
1291 }
1292 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001293 spin_unlock(&pHddCtx->filter_lock);
1294}
1295
1296
1297
1298void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx)
1299{
1300 v_CONTEXT_t pVosContext;
1301 tHalHandle smeContext;
1302
1303 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1304 if (NULL == pVosContext)
1305 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001306 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001307 return;
1308 }
1309 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1310 if (NULL == smeContext)
1311 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001312 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001313 return;
1314 }
1315
1316 spin_lock_init(&pHddCtx->filter_lock);
1317 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1318 pHddCtx->cfg_ini->nEnableSuspend)
1319 {
1320 pmcRegisterDeviceStateUpdateInd(smeContext,
1321 hdd_PowerStateChangedCB, pHddCtx);
1322 }
1323}
1324
1325void hdd_unregister_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 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1344 pHddCtx->cfg_ini->nEnableSuspend)
1345 {
1346 pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB);
1347 }
1348}
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301349
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301350#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301351void hdd_conf_gtk_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301352{
1353 eHalStatus ret;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301354 tSirGtkOffloadParams hddGtkOffloadReqParams;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301355 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1356
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301357 if(fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301358 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301359 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1360 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags ))
1361 {
1362 vos_mem_copy(&hddGtkOffloadReqParams,
1363 &pHddStaCtx->gtkOffloadReqParams,
1364 sizeof (tSirGtkOffloadParams));
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301365
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301366 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1367 &hddGtkOffloadReqParams, pAdapter->sessionId);
1368 if (eHAL_STATUS_SUCCESS != ret)
1369 {
1370 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1371 "%s: sme_SetGTKOffload failed, returned %d",
1372 __func__, ret);
1373 return;
1374 }
1375
1376 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1377 "%s: sme_SetGTKOffload successfull", __func__);
1378 }
1379
1380 }
1381 else
1382 {
1383 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1384 (0 == memcmp(&pHddStaCtx->gtkOffloadReqParams.bssId,
1385 &pHddStaCtx->conn_info.bssId, WNI_CFG_BSSID_LEN)) &&
1386 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags))
1387 {
1388
1389 /* Host driver has previously offloaded GTK rekey */
1390 ret = sme_GetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301391 wlan_hdd_cfg80211_update_replayCounterCallback,
1392 pAdapter, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301393 if (eHAL_STATUS_SUCCESS != ret)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301394
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301395 {
1396 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1397 "%s: sme_GetGTKOffload failed, returned %d",
1398 __func__, ret);
1399 return;
1400 }
1401 else
1402 {
1403 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1404 "%s: sme_GetGTKOffload successful",
1405 __func__);
1406
1407 /* Sending GTK offload dissable */
1408 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
1409 sizeof (tSirGtkOffloadParams));
1410 hddGtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE;
1411 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301412 &hddGtkOffloadReqParams, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301413 if (eHAL_STATUS_SUCCESS != ret)
1414 {
1415 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1416 "%s: failed to dissable GTK offload, returned %d",
1417 __func__, ret);
1418 return;
1419 }
1420 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1421 "%s: successfully dissabled GTK offload request to HAL",
1422 __func__);
1423 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301424 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301425 }
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301426 return;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301427}
1428#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
Jeff Johnson295189b2012-06-20 16:38:30 -07001429
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001430void hdd_resume_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001431{
1432 hdd_context_t *pHddCtx = NULL;
1433 hdd_adapter_t *pAdapter = NULL;
1434 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1435 VOS_STATUS status;
1436 v_CONTEXT_t pVosContext = NULL;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001437
Jeff Johnson295189b2012-06-20 16:38:30 -07001438 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
1439
1440 //Get the global VOSS context.
1441 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1442 if(!pVosContext) {
1443 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1444 return;
1445 }
1446
1447 //Get the HDD context.
1448 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1449
1450 if(!pHddCtx) {
1451 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1452 return;
1453 }
1454
1455 if (pHddCtx->isLogpInProgress) {
1456 hddLog(VOS_TRACE_LEVEL_INFO,
1457 "%s: Ignore resume wlan, LOGP in progress!", __func__);
1458 return;
1459 }
1460
Jeff Johnson295189b2012-06-20 16:38:30 -07001461 pHddCtx->hdd_wlan_suspended = FALSE;
1462 /*loop through all adapters. Concurrency */
1463 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1464
1465 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1466 {
1467 pAdapter = pAdapterNode->pAdapter;
1468 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001469 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001470 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001471 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001472 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1473 pAdapterNode = pNext;
1474 continue;
1475 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301476
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301477
Jeff Johnson295189b2012-06-20 16:38:30 -07001478#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1479 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP)
1480 {
1481 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__);
1482 hdd_exit_deep_sleep(pAdapter);
1483 }
1484#endif
1485
1486 if(pHddCtx->hdd_ignore_dtim_enabled == TRUE)
1487 {
1488 /*Switch back to DTIM 1*/
1489 tSirSetPowerParamsReq powerRequest = { 0 };
1490
1491 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
1492 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07001493 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001494
1495 /*Disabled ModulatedDTIM if enabled on suspend*/
1496 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1497 powerRequest.uDTIMPeriod = 0;
1498
1499 /* Update ignoreDTIM and ListedInterval in CFG with default values */
1500 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1501 NULL, eANI_BOOLEAN_FALSE);
1502 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1503 NULL, eANI_BOOLEAN_FALSE);
1504
1505 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001506 "Switch to DTIM%d",powerRequest.uListenInterval);
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08001507 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001508
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301509 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
1510 {
1511 /* put the device into full power */
1512 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001513
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301514 /* put the device back into BMPS */
1515 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
Jeff Johnson295189b2012-06-20 16:38:30 -07001516
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301517 pHddCtx->hdd_ignore_dtim_enabled = FALSE;
1518 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001519 }
1520
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301521 hdd_conf_resume_ind(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001522 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1523 pAdapterNode = pNext;
1524 }
1525
1526#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1527 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY)
1528 {
1529 hdd_exit_standby(pHddCtx);
1530 }
1531#endif
1532
Jeff Johnson295189b2012-06-20 16:38:30 -07001533 return;
1534}
1535
Jeff Johnson295189b2012-06-20 16:38:30 -07001536VOS_STATUS hdd_wlan_reset_initialization(void)
1537{
Jeff Johnson295189b2012-06-20 16:38:30 -07001538 v_CONTEXT_t pVosContext = NULL;
1539
1540 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1541
1542 //Get the global VOSS context.
1543 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1544 if(!pVosContext)
1545 {
1546 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1547 return VOS_STATUS_E_FAILURE;
1548 }
1549
1550 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__);
1551
1552 // Prevent the phone from going to sleep
1553 hdd_prevent_suspend();
1554
Jeff Johnson295189b2012-06-20 16:38:30 -07001555 return VOS_STATUS_SUCCESS;
1556}
1557
1558
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001559/*
1560 * Based on the ioctl command recieved by HDD, put WLAN driver
1561 * into the quiet mode. This is the same as the early suspend
1562 * notification that driver used to listen
1563 */
1564void hdd_set_wlan_suspend_mode(bool suspend)
Jeff Johnson295189b2012-06-20 16:38:30 -07001565{
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001566 if (suspend)
1567 hdd_suspend_wlan();
1568 else
1569 hdd_resume_wlan();
Jeff Johnson295189b2012-06-20 16:38:30 -07001570}
1571
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001572static void hdd_ssr_timer_init(void)
1573{
1574 init_timer(&ssr_timer);
1575}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001576
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001577static void hdd_ssr_timer_del(void)
1578{
1579 del_timer(&ssr_timer);
1580 ssr_timer_started = false;
1581}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001582
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001583static void hdd_ssr_timer_cb(unsigned long data)
1584{
1585 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD SSR timer expired", __func__);
Sameer Thalappile5637f42013-08-07 15:46:55 -07001586
1587#ifdef WCN_PRONTO
1588 if (wcnss_hardware_type() == WCNSS_PRONTO_HW)
1589 wcnss_pronto_log_debug_regs();
1590#endif
1591
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001592 VOS_BUG(0);
1593}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001594
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001595static void hdd_ssr_timer_start(int msec)
1596{
1597 if(ssr_timer_started)
1598 {
1599 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: trying to start SSR timer when it's running"
1600 ,__func__);
1601 }
1602 ssr_timer.expires = jiffies + msecs_to_jiffies(msec);
1603 ssr_timer.function = hdd_ssr_timer_cb;
1604 add_timer(&ssr_timer);
1605 ssr_timer_started = true;
1606}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001607
Jeff Johnson295189b2012-06-20 16:38:30 -07001608/* the HDD interface to WLAN driver shutdown,
1609 * the primary shutdown function in SSR
1610 */
1611VOS_STATUS hdd_wlan_shutdown(void)
1612{
1613 VOS_STATUS vosStatus;
1614 v_CONTEXT_t pVosContext = NULL;
1615 hdd_context_t *pHddCtx = NULL;
1616 pVosSchedContext vosSchedContext = NULL;
1617
1618 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__);
1619
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001620 /* if re-init never happens, then do SSR1 */
1621 hdd_ssr_timer_init();
1622 hdd_ssr_timer_start(HDD_SSR_BRING_UP_TIME);
1623
Jeff Johnson295189b2012-06-20 16:38:30 -07001624 /* Get the global VOSS context. */
1625 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1626 if(!pVosContext) {
1627 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1628 return VOS_STATUS_E_FAILURE;
1629 }
1630 /* Get the HDD context. */
1631 pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1632 if(!pHddCtx) {
1633 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1634 return VOS_STATUS_E_FAILURE;
1635 }
c_hpothud662a352013-12-26 15:09:12 +05301636
1637 //Stop the traffic monitor timer
1638 if ( VOS_TIMER_STATE_RUNNING ==
1639 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
1640 {
1641 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
1642 }
1643
Jeff Johnson295189b2012-06-20 16:38:30 -07001644 hdd_reset_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001645 /* DeRegister with platform driver as client for Suspend/Resume */
1646 vosStatus = hddDeregisterPmOps(pHddCtx);
1647 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1648 {
1649 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
1650 }
1651
1652 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
1653 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1654 {
1655 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
1656 }
1657
1658 /* Disable IMPS/BMPS as we do not want the device to enter any power
1659 * save mode on its own during reset sequence
1660 */
1661 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1662 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1663 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1664
1665 vosSchedContext = get_vos_sched_ctxt();
1666
1667 /* Wakeup all driver threads */
1668 if(TRUE == pHddCtx->isMcThreadSuspended){
1669 complete(&vosSchedContext->ResumeMcEvent);
1670 pHddCtx->isMcThreadSuspended= FALSE;
1671 }
1672 if(TRUE == pHddCtx->isTxThreadSuspended){
1673 complete(&vosSchedContext->ResumeTxEvent);
1674 pHddCtx->isTxThreadSuspended= FALSE;
1675 }
1676 if(TRUE == pHddCtx->isRxThreadSuspended){
1677 complete(&vosSchedContext->ResumeRxEvent);
1678 pHddCtx->isRxThreadSuspended= FALSE;
1679 }
1680 /* Reset the Suspend Variable */
1681 pHddCtx->isWlanSuspended = FALSE;
1682
1683 /* Stop all the threads; we do not want any messages to be a processed,
1684 * any more and the best way to ensure that is to terminate the threads
1685 * gracefully.
1686 */
1687 /* Wait for MC to exit */
1688 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
1689 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
1690 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
1691 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
Mihir Shete165143a2013-12-19 09:06:13 +05301692 wait_for_completion(&vosSchedContext->McShutdown);
Jeff Johnson295189b2012-06-20 16:38:30 -07001693
1694 /* Wait for TX to exit */
1695 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
1696 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
1697 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
1698 wake_up_interruptible(&vosSchedContext->txWaitQueue);
Mihir Shete165143a2013-12-19 09:06:13 +05301699 wait_for_completion(&vosSchedContext->TxShutdown);
Jeff Johnson295189b2012-06-20 16:38:30 -07001700
1701 /* Wait for RX to exit */
1702 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
1703 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
1704 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
1705 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
Mihir Shete165143a2013-12-19 09:06:13 +05301706 wait_for_completion(&vosSchedContext->RxShutdown);
Jeff Johnson295189b2012-06-20 16:38:30 -07001707
1708#ifdef WLAN_BTAMP_FEATURE
1709 vosStatus = WLANBAP_Stop(pVosContext);
1710 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1711 {
1712 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1713 "%s: Failed to stop BAP",__func__);
1714 }
1715#endif //WLAN_BTAMP_FEATURE
1716 vosStatus = vos_wda_shutdown(pVosContext);
1717 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1718
1719 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
1720 /* Stop SME - Cannot invoke vos_stop as vos_stop relies
1721 * on threads being running to process the SYS Stop
1722 */
Kiet Lama72a2322013-11-15 11:18:11 +05301723 vosStatus = sme_Stop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
Jeff Johnson295189b2012-06-20 16:38:30 -07001724 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1725
1726 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
1727 /* Stop MAC (PE and HAL) */
1728 vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
1729 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1730
1731 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
1732 /* Stop TL */
1733 vosStatus = WLANTL_Stop(pVosContext);
1734 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1735
Jeff Johnson295189b2012-06-20 16:38:30 -07001736 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001737 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__);
1738 /* Clean up message queues of TX and MC thread */
1739 vos_sched_flush_mc_mqs(vosSchedContext);
1740 vos_sched_flush_tx_mqs(vosSchedContext);
1741 vos_sched_flush_rx_mqs(vosSchedContext);
1742
1743 /* Deinit all the TX and MC queues */
1744 vos_sched_deinit_mqs(vosSchedContext);
1745 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__);
1746
1747 /* shutdown VOSS */
1748 vos_shutdown(pVosContext);
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05301749
1750 /*mac context has already been released in mac_close call
1751 so setting it to NULL in hdd context*/
1752 pHddCtx->hHal = (tHalHandle)NULL;
1753
Jeff Johnson295189b2012-06-20 16:38:30 -07001754 if (free_riva_power_on_lock("wlan"))
1755 {
1756 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
1757 __func__);
1758 }
1759 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete"
1760 ,__func__);
1761 return VOS_STATUS_SUCCESS;
1762}
1763
1764
1765
1766/* the HDD interface to WLAN driver re-init.
1767 * This is called to initialize/start WLAN driver after a shutdown.
1768 */
1769VOS_STATUS hdd_wlan_re_init(void)
1770{
1771 VOS_STATUS vosStatus;
1772 v_CONTEXT_t pVosContext = NULL;
1773 hdd_context_t *pHddCtx = NULL;
1774 eHalStatus halStatus;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07001775#ifdef HAVE_WCNSS_CAL_DOWNLOAD
1776 int max_retries = 0;
1777#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001778#ifdef WLAN_BTAMP_FEATURE
1779 hdd_config_t *pConfig = NULL;
1780 WLANBAP_ConfigType btAmpConfig;
1781#endif
1782
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001783 hdd_ssr_timer_del();
Jeff Johnson295189b2012-06-20 16:38:30 -07001784 hdd_prevent_suspend();
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001785
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07001786#ifdef HAVE_WCNSS_CAL_DOWNLOAD
1787 /* wait until WCNSS driver downloads NV */
1788 while (!wcnss_device_ready() && 5 >= ++max_retries) {
1789 msleep(1000);
1790 }
1791 if (max_retries >= 5) {
1792 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
1793 goto err_re_init;
1794 }
1795#endif
1796
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07001797 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, TRUE);
1798
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001799 /* The driver should always be initialized in STA mode after SSR */
1800 hdd_set_conparam(0);
1801
Jeff Johnson295189b2012-06-20 16:38:30 -07001802 /* Re-open VOSS, it is a re-open b'se control transport was never closed. */
1803 vosStatus = vos_open(&pVosContext, 0);
1804 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1805 {
1806 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
1807 goto err_re_init;
1808 }
1809
1810 /* Get the HDD context. */
1811 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1812 if(!pHddCtx)
1813 {
1814 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1815 goto err_vosclose;
1816 }
1817
1818 /* Save the hal context in Adapter */
1819 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
1820 if ( NULL == pHddCtx->hHal )
1821 {
1822 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
1823 goto err_vosclose;
1824 }
1825
1826 /* Set the SME configuration parameters. */
1827 vosStatus = hdd_set_sme_config(pHddCtx);
1828 if ( VOS_STATUS_SUCCESS != vosStatus )
1829 {
1830 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
1831 goto err_vosclose;
1832 }
1833
1834 /* Initialize the WMM module */
1835 vosStatus = hdd_wmm_init(pHddCtx);
1836 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
1837 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001838 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001839 goto err_vosclose;
1840 }
1841
1842 vosStatus = vos_preStart( pHddCtx->pvosContext );
1843 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1844 {
1845 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
1846 goto err_vosclose;
1847 }
1848
1849 /* In the integrated architecture we update the configuration from
1850 the INI file and from NV before vOSS has been started so that
1851 the final contents are available to send down to the cCPU */
1852 /* Apply the cfg.ini to cfg.dat */
1853 if (FALSE == hdd_update_config_dat(pHddCtx))
1854 {
1855 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
1856 goto err_vosclose;
1857 }
1858
1859 /* Set the MAC Address, currently this is used by HAL to add self sta.
1860 * Remove this once self sta is added as part of session open. */
1861 halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID,
1862 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
1863 sizeof(pHddCtx->cfg_ini->intfMacAddr[0]));
1864 if (!HAL_STATUS_SUCCESS(halStatus))
1865 {
1866 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
1867 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus);
1868 goto err_vosclose;
1869 }
1870
1871 /* Start VOSS which starts up the SME/MAC/HAL modules and everything else
1872 Note: Firmware image will be read and downloaded inside vos_start API */
1873 vosStatus = vos_start( pVosContext );
1874 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1875 {
1876 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
1877 goto err_vosclose;
1878 }
1879
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07001880 /* Exchange capability info between Host and FW and also get versioning info from FW */
1881 hdd_exchange_version_and_caps(pHddCtx);
1882
Jeff Johnson295189b2012-06-20 16:38:30 -07001883 vosStatus = hdd_post_voss_start_config( pHddCtx );
1884 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1885 {
1886 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
1887 __func__);
1888 goto err_vosstop;
1889 }
1890
1891#ifdef WLAN_BTAMP_FEATURE
1892 vosStatus = WLANBAP_Open(pVosContext);
1893 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1894 {
1895 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1896 "%s: Failed to open BAP",__func__);
1897 goto err_vosstop;
1898 }
1899 vosStatus = BSL_Init(pVosContext);
1900 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1901 {
1902 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1903 "%s: Failed to Init BSL",__func__);
1904 goto err_bap_close;
1905 }
1906 vosStatus = WLANBAP_Start(pVosContext);
1907 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1908 {
1909 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1910 "%s: Failed to start TL",__func__);
1911 goto err_bap_close;
1912 }
1913 pConfig = pHddCtx->cfg_ini;
1914 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
1915 vosStatus = WLANBAP_SetConfig(&btAmpConfig);
1916#endif //WLAN_BTAMP_FEATURE
1917
1918 /* Restart all adapters */
1919 hdd_start_all_adapters(pHddCtx);
1920 pHddCtx->isLogpInProgress = FALSE;
Sameer Thalappilb511beb2013-09-09 17:11:51 -07001921 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001922 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001923 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001924
1925 /* Register with platform driver as client for Suspend/Resume */
1926 vosStatus = hddRegisterPmOps(pHddCtx);
1927 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1928 {
1929 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
1930 goto err_bap_stop;
1931 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001932 /* Allow the phone to go to sleep */
1933 hdd_allow_suspend();
1934 /* register for riva power on lock */
1935 if (req_riva_power_on_lock("wlan"))
1936 {
1937 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
1938 __func__);
1939 goto err_unregister_pmops;
1940 }
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07001941 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001942 goto success;
1943
1944err_unregister_pmops:
1945 hddDeregisterPmOps(pHddCtx);
1946
1947err_bap_stop:
Jeff Johnson32d95a32012-09-10 13:15:23 -07001948#ifdef CONFIG_HAS_EARLYSUSPEND
1949 hdd_unregister_mcast_bcast_filter(pHddCtx);
1950#endif
1951 hdd_close_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001952#ifdef WLAN_BTAMP_FEATURE
Jeff Johnson32d95a32012-09-10 13:15:23 -07001953 WLANBAP_Stop(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07001954#endif
1955
1956#ifdef WLAN_BTAMP_FEATURE
1957err_bap_close:
1958 WLANBAP_Close(pVosContext);
1959#endif
1960
1961err_vosstop:
1962 vos_stop(pVosContext);
1963
1964err_vosclose:
1965 vos_close(pVosContext);
1966 vos_sched_close(pVosContext);
1967 if (pHddCtx)
1968 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001969 /* Unregister the Net Device Notifier */
1970 unregister_netdevice_notifier(&hdd_netdev_notifier);
1971 /* Clean up HDD Nlink Service */
1972 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07001973#ifdef WLAN_KD_READY_NOTIFIER
1974 nl_srv_exit(pHddCtx->ptt_pid);
1975#else
Jeff Johnson295189b2012-06-20 16:38:30 -07001976 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07001977#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07001978 /* Free up dynamically allocated members inside HDD Adapter */
1979 kfree(pHddCtx->cfg_ini);
1980 pHddCtx->cfg_ini= NULL;
1981
Jeff Johnson295189b2012-06-20 16:38:30 -07001982 wiphy_unregister(pHddCtx->wiphy);
1983 wiphy_free(pHddCtx->wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07001984 }
1985 vos_preClose(&pVosContext);
1986
1987#ifdef MEMORY_DEBUG
1988 vos_mem_exit();
1989#endif
1990
1991err_re_init:
1992 /* Allow the phone to go to sleep */
1993 hdd_allow_suspend();
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07001994 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07001995 VOS_BUG(0);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001996 return -EPERM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001997
1998success:
1999 /* Trigger replay of BTC events */
2000 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
2001 return VOS_STATUS_SUCCESS;
2002}