blob: 042bf1b67645d85266bbfaebd90b595e07bc9e3c [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
769 if (eHAL_STATUS_SUCCESS !=
770 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
771 pAdapter->sessionId, &offLoadRequest))
772 {
773 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failure to disable"
774 "NSOffload feature"));
775 }
776 }
777 return;
778}
779#endif
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530780
781void hdd_ipv4_notifier_work_queue(struct work_struct *work)
782{
783 hdd_adapter_t* pAdapter =
784 container_of(work, hdd_adapter_t, ipv4NotifierWorkQueue);
785 hdd_context_t *pHddCtx;
786 int status;
787
788 hddLog(LOG1, FL("Reconfiguring ARP Offload"));
789 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
790 status = wlan_hdd_validate_context(pHddCtx);
791 if (0 != status)
792 {
793 hddLog(LOGE, FL("HDD context is invalid"));
794 return;
795 }
796
797 if ((eConnectionState_Associated ==
798 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)
799 && (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid))
800 {
801 // This invocation being part of the IPv4 registration callback,
802 // we are passing second parameter as 2 to avoid registration
803 // of IPv4 notifier again.
804 hdd_conf_arp_offload(pAdapter, 2);
805 }
806}
807
808static int wlan_hdd_ipv4_changed(struct notifier_block *nb,
809 unsigned long data, void *arg)
810{
811 struct in_ifaddr *ifa = (struct in_ifaddr *)arg;
812 struct in_ifaddr **ifap = NULL;
813 struct in_device *in_dev;
814
815 struct net_device *ndev = ifa->ifa_dev->dev;
816 hdd_adapter_t *pAdapter =
817 container_of(nb, struct hdd_adapter_s, ipv4_notifier);
818
819 if (pAdapter && pAdapter->dev == ndev)
820 {
821 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
822 {
823 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
824 ifap = &ifa->ifa_next)
825 {
826 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
827 {
828 break; /* found */
829 }
830 }
831 }
832 if(ifa && ifa->ifa_local)
833 {
834 schedule_work(&pAdapter->ipv4NotifierWorkQueue);
835 }
836 }
837
838 return NOTIFY_DONE;
839}
840
841/**----------------------------------------------------------------------------
842
843 \brief hdd_conf_arp_offload() - Configure ARP offload
844
845 Called during SUSPEND to configure the ARP offload (MC BC filter) which
846 reduces power consumption.
847
848 \param - pAdapter -Adapter context for which ARP offload is to be configured
849 \param - fenable - 0 - disable.
850 1 - enable. (with IPv4 notifier registration)
851 2 - enable. (without IPv4 notifier registration)
852
853 \return -
854 VOS_STATUS_SUCCESS - on successful operation
855 VOS_STATUS_E_FAILURE - on failure of operation
856-----------------------------------------------------------------------------*/
857VOS_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, int fenable)
Jeff Johnson295189b2012-06-20 16:38:30 -0700858{
859 struct in_ifaddr **ifap = NULL;
860 struct in_ifaddr *ifa = NULL;
861 struct in_device *in_dev;
862 int i = 0;
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530863 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700864 tSirHostOffloadReq offLoadRequest;
Yathish9f22e662012-12-10 14:21:35 -0800865 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700866
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530867 hddLog(VOS_TRACE_LEVEL_ERROR, FL(" fenable = %d \n"), fenable);
Jeff Johnson295189b2012-06-20 16:38:30 -0700868
Jeff Johnson295189b2012-06-20 16:38:30 -0700869 if(fenable)
870 {
871 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
872 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530873 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700874 ifap = &ifa->ifa_next)
875 {
876 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
877 {
878 break; /* found */
879 }
880 }
881 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700882 if(ifa && ifa->ifa_local)
883 {
884 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
885 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
886
Arif Hussain6d2a3322013-11-17 19:50:10 -0800887 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700888
Amar Singhald53568e2013-09-26 11:03:45 -0700889 if (((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
890 pHddCtx->sus_res_mcastbcast_filter) ||
891 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
892 pHddCtx->sus_res_mcastbcast_filter)) &&
893 (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid))
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700894 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530895 offLoadRequest.enableOrDisable =
Amar Singhald53568e2013-09-26 11:03:45 -0700896 SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
897 hddLog(VOS_TRACE_LEVEL_INFO,
898 "offload: inside arp offload conditional check");
Jeff Johnson295189b2012-06-20 16:38:30 -0700899 }
Amar Singhald53568e2013-09-26 11:03:45 -0700900
901 hddLog(VOS_TRACE_LEVEL_INFO, "offload: arp filter programmed = %d",
902 offLoadRequest.enableOrDisable);
903
Jeff Johnson295189b2012-06-20 16:38:30 -0700904 //converting u32 to IPV4 address
905 for(i = 0 ; i < 4; i++)
906 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530907 offLoadRequest.params.hostIpv4Addr[i] =
Jeff Johnson295189b2012-06-20 16:38:30 -0700908 (ifa->ifa_local >> (i*8) ) & 0xFF ;
909 }
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530910 hddLog(VOS_TRACE_LEVEL_INFO, " Enable SME HostOffload: %d.%d.%d.%d",
Jeff Johnson295189b2012-06-20 16:38:30 -0700911 offLoadRequest.params.hostIpv4Addr[0],
912 offLoadRequest.params.hostIpv4Addr[1],
913 offLoadRequest.params.hostIpv4Addr[2],
914 offLoadRequest.params.hostIpv4Addr[3]);
915
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530916 if (eHAL_STATUS_SUCCESS !=
917 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
918 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700919 {
920 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to enable HostOffload "
Arif Hussain6d2a3322013-11-17 19:50:10 -0800921 "feature", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700922 return VOS_STATUS_E_FAILURE;
923 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700924 }
925 else
926 {
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530927 hddLog(VOS_TRACE_LEVEL_INFO, FL("IP Address is not assigned\n"));
Jeff Johnson295189b2012-06-20 16:38:30 -0700928 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530929
930 if (fenable == 1)
931 {
932 // Register IPv4 notifier to notify if any change in IP
933 // So that we can reconfigure the offload parameters
934 pAdapter->ipv4_notifier.notifier_call =
935 wlan_hdd_ipv4_changed;
936 ret = register_inetaddr_notifier(&pAdapter->ipv4_notifier);
937 if (ret)
938 {
939 hddLog(LOGE, FL("Failed to register IPv4 notifier"));
940 }
941 }
942 return VOS_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -0700943 }
944 else
945 {
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530946 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
Jeff Johnson295189b2012-06-20 16:38:30 -0700947 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
948 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
949 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
950
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530951 if (eHAL_STATUS_SUCCESS !=
952 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
953 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700954 {
955 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to disable host "
Arif Hussain6d2a3322013-11-17 19:50:10 -0800956 "offload feature", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700957 return VOS_STATUS_E_FAILURE;
958 }
959 return VOS_STATUS_SUCCESS;
960 }
961}
962
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530963/*
964 * This function is called before setting mcbc filters
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530965 * to modify filter value considering Different Offloads
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530966*/
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530967void hdd_mcbc_filter_modification(hdd_context_t* pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530968 tANI_U8 *pMcBcFilter)
969{
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530970 if (NULL == pHddCtx)
971 {
972 hddLog(VOS_TRACE_LEVEL_ERROR, FL("NULL HDD context passed"));
973 return;
974 }
975
976 *pMcBcFilter = pHddCtx->configuredMcastBcastFilter;
977 if (pHddCtx->cfg_ini->fhostArpOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530978 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +0530979 /* ARP offload is enabled, do not block bcast packets at RXP
980 * Will be using Bitmasking to reset the filter. As we have
981 * disable Broadcast filtering, Anding with the negation
982 * of Broadcast BIT
983 */
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530984 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530985 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530986
987#ifdef WLAN_NS_OFFLOAD
988 if (pHddCtx->cfg_ini->fhostNSOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530989 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530990 /* NS offload is enabled, do not block mcast packets at RXP
991 * Will be using Bitmasking to reset the filter. As we have
992 * disable Multicast filtering, Anding with the negation
993 * of Multicast BIT
994 */
995 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530996 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530997#endif
998
999 pHddCtx->configuredMcastBcastFilter = *pMcBcFilter;
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301000}
1001
Jeff Johnson295189b2012-06-20 16:38:30 -07001002void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter)
1003{
1004 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001005 tpSirWlanSetRxpFilters wlanRxpFilterParam =
1006 vos_mem_malloc(sizeof(tSirWlanSetRxpFilters));
1007 if(NULL == wlanRxpFilterParam)
1008 {
1009 hddLog(VOS_TRACE_LEVEL_FATAL,
1010 "%s: vos_mem_alloc failed ", __func__);
1011 return;
1012 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001013 hddLog(VOS_TRACE_LEVEL_INFO,
1014 "%s: Configuring Mcast/Bcast Filter Setting. setfilter %d", __func__, setfilter);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301015 if (TRUE == setfilter)
1016 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301017 hdd_mcbc_filter_modification(pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301018 &wlanRxpFilterParam->configuredMcstBcstFilterSetting);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301019 }
1020 else
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301021 {
1022 /*Use the current configured value to clear*/
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301023 wlanRxpFilterParam->configuredMcstBcstFilterSetting =
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301024 pHddCtx->configuredMcastBcastFilter;
1025 }
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301026
Jeff Johnson295189b2012-06-20 16:38:30 -07001027 wlanRxpFilterParam->setMcstBcstFilter = setfilter;
Jeff Johnson295189b2012-06-20 16:38:30 -07001028 halStatus = sme_ConfigureRxpFilter(pHddCtx->hHal, wlanRxpFilterParam);
Chilam Ngc4244af2013-04-01 15:37:32 -07001029 if (eHAL_STATUS_SUCCESS != halStatus)
1030 vos_mem_free(wlanRxpFilterParam);
Jeff Johnson295189b2012-06-20 16:38:30 -07001031 if(setfilter && (eHAL_STATUS_SUCCESS == halStatus))
1032 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
1033}
1034
Jeff Johnson295189b2012-06-20 16:38:30 -07001035static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx,
1036 hdd_adapter_t *pAdapter)
1037{
1038 eHalStatus halStatus = eHAL_STATUS_FAILURE;
1039 tpSirWlanSuspendParam wlanSuspendParam =
1040 vos_mem_malloc(sizeof(tSirWlanSuspendParam));
1041
Amar Singhald53568e2013-09-26 11:03:45 -07001042 if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid) {
1043 pHddCtx->sus_res_mcastbcast_filter =
1044 pHddCtx->configuredMcastBcastFilter;
1045 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
1046 hddLog(VOS_TRACE_LEVEL_INFO, "offload: hdd_conf_suspend_ind");
1047 hddLog(VOS_TRACE_LEVEL_INFO, "configuredMCastBcastFilter saved = %d",
1048 pHddCtx->configuredMcastBcastFilter);
1049
1050 }
1051
Amar Singhal49fdfd52013-08-13 13:25:12 -07001052
Jeff Johnson295189b2012-06-20 16:38:30 -07001053 if(NULL == wlanSuspendParam)
1054 {
1055 hddLog(VOS_TRACE_LEVEL_FATAL,
1056 "%s: vos_mem_alloc failed ", __func__);
1057 return;
1058 }
1059
Amar Singhald53568e2013-09-26 11:03:45 -07001060 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001061 "%s: send wlan suspend indication", __func__);
1062
1063 if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER))
1064 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301065 //Configure supported OffLoads
1066 hdd_conf_hostoffload(pAdapter, TRUE);
1067 wlanSuspendParam->configuredMcstBcstFilterSetting = pHddCtx->configuredMcastBcastFilter;
Jeff Johnson295189b2012-06-20 16:38:30 -07001068
1069#ifdef WLAN_FEATURE_PACKET_FILTERING
madan mohan koyyalamudibfd9cef2013-07-01 18:39:37 +05301070 /* During suspend, configure MC Addr list filter to the firmware
1071 * function takes care of checking necessary conditions before
1072 * configuring.
1073 */
1074 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001075#endif
1076 }
1077
1078 halStatus = sme_ConfigureSuspendInd(pHddCtx->hHal, wlanSuspendParam);
1079 if(eHAL_STATUS_SUCCESS == halStatus)
1080 {
1081 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
Chilam Ngc4244af2013-04-01 15:37:32 -07001082 } else {
1083 vos_mem_free(wlanSuspendParam);
Jeff Johnson295189b2012-06-20 16:38:30 -07001084 }
1085}
1086
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301087static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001088{
Chilam Ngc4244af2013-04-01 15:37:32 -07001089 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Yathish9f22e662012-12-10 14:21:35 -08001090 hdd_context_t* pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Chilam Ngc4244af2013-04-01 15:37:32 -07001091 tpSirWlanResumeParam wlanResumeParam;
Jeff Johnson295189b2012-06-20 16:38:30 -07001092
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301093 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001094 "%s: send wlan resume indication", __func__);
1095
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301096 wlanResumeParam = vos_mem_malloc(sizeof(tSirWlanResumeParam));
1097
1098 if (NULL == wlanResumeParam)
Jeff Johnson295189b2012-06-20 16:38:30 -07001099 {
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301100 hddLog(VOS_TRACE_LEVEL_FATAL,
1101 "%s: memory allocation failed for wlanResumeParam ", __func__);
1102 return;
Jeff Johnson295189b2012-06-20 16:38:30 -07001103 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001104
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301105 //Disable supported OffLoads
1106 hdd_conf_hostoffload(pAdapter, FALSE);
1107
1108 wlanResumeParam->configuredMcstBcstFilterSetting =
1109 pHddCtx->configuredMcastBcastFilter;
1110 halStatus = sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam);
1111 if (eHAL_STATUS_SUCCESS != halStatus)
1112 {
1113 vos_mem_free(wlanResumeParam);
1114 }
1115
1116 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
1117
Amar Singhalf8ba2b82013-12-02 12:54:38 -08001118 if (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid) {
1119 pHddCtx->configuredMcastBcastFilter =
1120 pHddCtx->sus_res_mcastbcast_filter;
1121 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_FALSE;
1122 }
Amar Singhald53568e2013-09-26 11:03:45 -07001123
1124 hddLog(VOS_TRACE_LEVEL_INFO,
1125 "offload: in hdd_conf_resume_ind, restoring configuredMcastBcastFilter");
1126 hddLog(VOS_TRACE_LEVEL_INFO, "configuredMcastBcastFilter = %d",
1127 pHddCtx->configuredMcastBcastFilter);
Amar Singhal49fdfd52013-08-13 13:25:12 -07001128
Chilam Ngc4244af2013-04-01 15:37:32 -07001129
madan mohan koyyalamudibfd9cef2013-07-01 18:39:37 +05301130#ifdef WLAN_FEATURE_PACKET_FILTERING
1131 /* Filer was applied during suspend inditication
1132 * clear it when we resume.
1133 */
1134 wlan_hdd_set_mc_addr_list(pAdapter, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001135#endif
1136}
Jeff Johnson295189b2012-06-20 16:38:30 -07001137
Jeff Johnson295189b2012-06-20 16:38:30 -07001138//Suspend routine registered with Android OS
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001139void hdd_suspend_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001140{
1141 hdd_context_t *pHddCtx = NULL;
1142 v_CONTEXT_t pVosContext = NULL;
1143
Jeff Johnson295189b2012-06-20 16:38:30 -07001144 VOS_STATUS status;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301145 hdd_adapter_t *pAdapter = NULL;
1146 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301147 bool hdd_enter_bmps = FALSE;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001148
Jeff Johnson295189b2012-06-20 16:38:30 -07001149 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__);
1150
1151 //Get the global VOSS context.
1152 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1153 if(!pVosContext) {
1154 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1155 return;
1156 }
1157
1158 //Get the HDD context.
1159 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1160
1161 if(!pHddCtx) {
1162 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1163 return;
1164 }
1165
1166 if (pHddCtx->isLogpInProgress) {
1167 hddLog(VOS_TRACE_LEVEL_ERROR,
1168 "%s: Ignore suspend wlan, LOGP in progress!", __func__);
1169 return;
1170 }
1171
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301172 hdd_set_pwrparams(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001173 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1174 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1175 {
1176 pAdapter = pAdapterNode->pAdapter;
1177 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001178 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001179 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
1180
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001181 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001182 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1183 pAdapterNode = pNext;
1184 continue;
1185 }
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301186 /* Avoid multiple enter/exit BMPS in this while loop using
1187 * hdd_enter_bmps flag
1188 */
1189 if (FALSE == hdd_enter_bmps && (BMPS == pmcGetPmcState(pHddCtx->hHal)))
1190 {
1191 hdd_enter_bmps = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001192
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301193 /* If device was already in BMPS, and dynamic DTIM is set,
1194 * exit(set the device to full power) and enter BMPS again
1195 * to reflect new DTIM value */
1196 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
1197
1198 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
1199
1200 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1201 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001202#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1203 if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1204 {
1205 //stop the interface before putting the chip to standby
1206 netif_tx_disable(pAdapter->dev);
1207 netif_carrier_off(pAdapter->dev);
1208 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301209 else if (pHddCtx->cfg_ini->nEnableSuspend ==
Jeff Johnson295189b2012-06-20 16:38:30 -07001210 WLAN_MAP_SUSPEND_TO_DEEP_SLEEP)
1211 {
1212 //Execute deep sleep procedure
1213 hdd_enter_deep_sleep(pHddCtx, pAdapter);
1214 }
1215#endif
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301216
1217 /*Suspend notification sent down to driver*/
1218 hdd_conf_suspend_ind(pHddCtx, pAdapter);
1219
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301220 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1221 pAdapterNode = pNext;
1222 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301223 pHddCtx->hdd_wlan_suspended = TRUE;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301224
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 hdd_enter_standby(pHddCtx);
1229 }
1230#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001231
1232 return;
1233}
1234
1235static void hdd_PowerStateChangedCB
1236(
1237 v_PVOID_t callbackContext,
1238 tPmcState newState
1239)
1240{
1241 hdd_context_t *pHddCtx = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07001242 /* if the driver was not in BMPS during early suspend,
1243 * the dynamic DTIM is now updated at Riva */
1244 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended
1245 && pHddCtx->cfg_ini->enableDynamicDTIM
1246 && (pHddCtx->hdd_ignore_dtim_enabled == FALSE))
1247 {
1248 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1249 }
1250 spin_lock(&pHddCtx->filter_lock);
Gopichand Nakkalac1b11522013-03-25 15:25:33 +05301251 if((newState == BMPS) && pHddCtx->hdd_wlan_suspended) {
Jeff Johnson295189b2012-06-20 16:38:30 -07001252 spin_unlock(&pHddCtx->filter_lock);
Amar Singhald53568e2013-09-26 11:03:45 -07001253 if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid) {
1254 pHddCtx->sus_res_mcastbcast_filter =
1255 pHddCtx->configuredMcastBcastFilter;
1256 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
1257
1258 hddLog(VOS_TRACE_LEVEL_INFO, "offload: callback to associated");
1259 hddLog(VOS_TRACE_LEVEL_INFO, "saving configuredMcastBcastFilter = %d",
1260 pHddCtx->configuredMcastBcastFilter);
1261 hddLog(VOS_TRACE_LEVEL_INFO,
1262 "offload: calling hdd_conf_mcastbcast_filter");
1263
1264 }
1265
Jeff Johnson295189b2012-06-20 16:38:30 -07001266 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001267 if(pHddCtx->hdd_mcastbcast_filter_set != TRUE)
1268 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__);
1269 }
Amar Singhal49fdfd52013-08-13 13:25:12 -07001270 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001271 spin_unlock(&pHddCtx->filter_lock);
1272}
1273
1274
1275
1276void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx)
1277{
1278 v_CONTEXT_t pVosContext;
1279 tHalHandle smeContext;
1280
1281 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1282 if (NULL == pVosContext)
1283 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001284 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001285 return;
1286 }
1287 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1288 if (NULL == smeContext)
1289 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001290 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001291 return;
1292 }
1293
1294 spin_lock_init(&pHddCtx->filter_lock);
1295 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1296 pHddCtx->cfg_ini->nEnableSuspend)
1297 {
1298 pmcRegisterDeviceStateUpdateInd(smeContext,
1299 hdd_PowerStateChangedCB, pHddCtx);
1300 }
1301}
1302
1303void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx)
1304{
1305 v_CONTEXT_t pVosContext;
1306 tHalHandle smeContext;
1307
1308 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1309 if (NULL == pVosContext)
1310 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001311 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001312 return;
1313 }
1314 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1315 if (NULL == smeContext)
1316 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001317 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001318 return;
1319 }
1320
1321 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1322 pHddCtx->cfg_ini->nEnableSuspend)
1323 {
1324 pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB);
1325 }
1326}
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301327
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301328#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301329void hdd_conf_gtk_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301330{
1331 eHalStatus ret;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301332 tSirGtkOffloadParams hddGtkOffloadReqParams;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301333 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1334
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301335 if(fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301336 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301337 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1338 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags ))
1339 {
1340 vos_mem_copy(&hddGtkOffloadReqParams,
1341 &pHddStaCtx->gtkOffloadReqParams,
1342 sizeof (tSirGtkOffloadParams));
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301343
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301344 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1345 &hddGtkOffloadReqParams, pAdapter->sessionId);
1346 if (eHAL_STATUS_SUCCESS != ret)
1347 {
1348 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1349 "%s: sme_SetGTKOffload failed, returned %d",
1350 __func__, ret);
1351 return;
1352 }
1353
1354 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1355 "%s: sme_SetGTKOffload successfull", __func__);
1356 }
1357
1358 }
1359 else
1360 {
1361 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1362 (0 == memcmp(&pHddStaCtx->gtkOffloadReqParams.bssId,
1363 &pHddStaCtx->conn_info.bssId, WNI_CFG_BSSID_LEN)) &&
1364 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags))
1365 {
1366
1367 /* Host driver has previously offloaded GTK rekey */
1368 ret = sme_GetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301369 wlan_hdd_cfg80211_update_replayCounterCallback,
1370 pAdapter, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301371 if (eHAL_STATUS_SUCCESS != ret)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301372
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301373 {
1374 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1375 "%s: sme_GetGTKOffload failed, returned %d",
1376 __func__, ret);
1377 return;
1378 }
1379 else
1380 {
1381 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1382 "%s: sme_GetGTKOffload successful",
1383 __func__);
1384
1385 /* Sending GTK offload dissable */
1386 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
1387 sizeof (tSirGtkOffloadParams));
1388 hddGtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE;
1389 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301390 &hddGtkOffloadReqParams, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301391 if (eHAL_STATUS_SUCCESS != ret)
1392 {
1393 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1394 "%s: failed to dissable GTK offload, returned %d",
1395 __func__, ret);
1396 return;
1397 }
1398 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1399 "%s: successfully dissabled GTK offload request to HAL",
1400 __func__);
1401 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301402 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301403 }
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301404 return;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301405}
1406#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
Jeff Johnson295189b2012-06-20 16:38:30 -07001407
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001408void hdd_resume_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001409{
1410 hdd_context_t *pHddCtx = NULL;
1411 hdd_adapter_t *pAdapter = NULL;
1412 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1413 VOS_STATUS status;
1414 v_CONTEXT_t pVosContext = NULL;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001415
Jeff Johnson295189b2012-06-20 16:38:30 -07001416 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
1417
1418 //Get the global VOSS context.
1419 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1420 if(!pVosContext) {
1421 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1422 return;
1423 }
1424
1425 //Get the HDD context.
1426 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1427
1428 if(!pHddCtx) {
1429 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1430 return;
1431 }
1432
1433 if (pHddCtx->isLogpInProgress) {
1434 hddLog(VOS_TRACE_LEVEL_INFO,
1435 "%s: Ignore resume wlan, LOGP in progress!", __func__);
1436 return;
1437 }
1438
Jeff Johnson295189b2012-06-20 16:38:30 -07001439 pHddCtx->hdd_wlan_suspended = FALSE;
1440 /*loop through all adapters. Concurrency */
1441 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1442
1443 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1444 {
1445 pAdapter = pAdapterNode->pAdapter;
1446 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001447 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001448 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001449 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001450 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1451 pAdapterNode = pNext;
1452 continue;
1453 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301454
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301455
Jeff Johnson295189b2012-06-20 16:38:30 -07001456#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1457 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP)
1458 {
1459 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__);
1460 hdd_exit_deep_sleep(pAdapter);
1461 }
1462#endif
1463
1464 if(pHddCtx->hdd_ignore_dtim_enabled == TRUE)
1465 {
1466 /*Switch back to DTIM 1*/
1467 tSirSetPowerParamsReq powerRequest = { 0 };
1468
1469 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
1470 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07001471 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001472
1473 /*Disabled ModulatedDTIM if enabled on suspend*/
1474 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1475 powerRequest.uDTIMPeriod = 0;
1476
1477 /* Update ignoreDTIM and ListedInterval in CFG with default values */
1478 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1479 NULL, eANI_BOOLEAN_FALSE);
1480 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1481 NULL, eANI_BOOLEAN_FALSE);
1482
1483 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001484 "Switch to DTIM%d",powerRequest.uListenInterval);
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08001485 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001486
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301487 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
1488 {
1489 /* put the device into full power */
1490 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001491
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301492 /* put the device back into BMPS */
1493 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
Jeff Johnson295189b2012-06-20 16:38:30 -07001494
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301495 pHddCtx->hdd_ignore_dtim_enabled = FALSE;
1496 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001497 }
1498
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301499 hdd_conf_resume_ind(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001500 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1501 pAdapterNode = pNext;
1502 }
1503
1504#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1505 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY)
1506 {
1507 hdd_exit_standby(pHddCtx);
1508 }
1509#endif
1510
Jeff Johnson295189b2012-06-20 16:38:30 -07001511 return;
1512}
1513
Jeff Johnson295189b2012-06-20 16:38:30 -07001514VOS_STATUS hdd_wlan_reset_initialization(void)
1515{
Jeff Johnson295189b2012-06-20 16:38:30 -07001516 v_CONTEXT_t pVosContext = NULL;
1517
1518 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1519
1520 //Get the global VOSS context.
1521 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1522 if(!pVosContext)
1523 {
1524 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1525 return VOS_STATUS_E_FAILURE;
1526 }
1527
1528 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__);
1529
1530 // Prevent the phone from going to sleep
1531 hdd_prevent_suspend();
1532
Jeff Johnson295189b2012-06-20 16:38:30 -07001533 return VOS_STATUS_SUCCESS;
1534}
1535
1536
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001537/*
1538 * Based on the ioctl command recieved by HDD, put WLAN driver
1539 * into the quiet mode. This is the same as the early suspend
1540 * notification that driver used to listen
1541 */
1542void hdd_set_wlan_suspend_mode(bool suspend)
Jeff Johnson295189b2012-06-20 16:38:30 -07001543{
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001544 if (suspend)
1545 hdd_suspend_wlan();
1546 else
1547 hdd_resume_wlan();
Jeff Johnson295189b2012-06-20 16:38:30 -07001548}
1549
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001550static void hdd_ssr_timer_init(void)
1551{
1552 init_timer(&ssr_timer);
1553}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001554
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001555static void hdd_ssr_timer_del(void)
1556{
1557 del_timer(&ssr_timer);
1558 ssr_timer_started = false;
1559}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001560
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001561static void hdd_ssr_timer_cb(unsigned long data)
1562{
1563 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD SSR timer expired", __func__);
Sameer Thalappile5637f42013-08-07 15:46:55 -07001564
1565#ifdef WCN_PRONTO
1566 if (wcnss_hardware_type() == WCNSS_PRONTO_HW)
1567 wcnss_pronto_log_debug_regs();
1568#endif
1569
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001570 VOS_BUG(0);
1571}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001572
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001573static void hdd_ssr_timer_start(int msec)
1574{
1575 if(ssr_timer_started)
1576 {
1577 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: trying to start SSR timer when it's running"
1578 ,__func__);
1579 }
1580 ssr_timer.expires = jiffies + msecs_to_jiffies(msec);
1581 ssr_timer.function = hdd_ssr_timer_cb;
1582 add_timer(&ssr_timer);
1583 ssr_timer_started = true;
1584}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001585
Jeff Johnson295189b2012-06-20 16:38:30 -07001586/* the HDD interface to WLAN driver shutdown,
1587 * the primary shutdown function in SSR
1588 */
1589VOS_STATUS hdd_wlan_shutdown(void)
1590{
1591 VOS_STATUS vosStatus;
1592 v_CONTEXT_t pVosContext = NULL;
1593 hdd_context_t *pHddCtx = NULL;
1594 pVosSchedContext vosSchedContext = NULL;
1595
1596 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__);
1597
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001598 /* if re-init never happens, then do SSR1 */
1599 hdd_ssr_timer_init();
1600 hdd_ssr_timer_start(HDD_SSR_BRING_UP_TIME);
1601
Jeff Johnson295189b2012-06-20 16:38:30 -07001602 /* Get the global VOSS context. */
1603 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1604 if(!pVosContext) {
1605 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1606 return VOS_STATUS_E_FAILURE;
1607 }
1608 /* Get the HDD context. */
1609 pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1610 if(!pHddCtx) {
1611 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1612 return VOS_STATUS_E_FAILURE;
1613 }
1614 hdd_reset_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001615 /* DeRegister with platform driver as client for Suspend/Resume */
1616 vosStatus = hddDeregisterPmOps(pHddCtx);
1617 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1618 {
1619 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
1620 }
1621
1622 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
1623 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1624 {
1625 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
1626 }
1627
1628 /* Disable IMPS/BMPS as we do not want the device to enter any power
1629 * save mode on its own during reset sequence
1630 */
1631 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1632 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1633 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1634
1635 vosSchedContext = get_vos_sched_ctxt();
1636
1637 /* Wakeup all driver threads */
1638 if(TRUE == pHddCtx->isMcThreadSuspended){
1639 complete(&vosSchedContext->ResumeMcEvent);
1640 pHddCtx->isMcThreadSuspended= FALSE;
1641 }
1642 if(TRUE == pHddCtx->isTxThreadSuspended){
1643 complete(&vosSchedContext->ResumeTxEvent);
1644 pHddCtx->isTxThreadSuspended= FALSE;
1645 }
1646 if(TRUE == pHddCtx->isRxThreadSuspended){
1647 complete(&vosSchedContext->ResumeRxEvent);
1648 pHddCtx->isRxThreadSuspended= FALSE;
1649 }
1650 /* Reset the Suspend Variable */
1651 pHddCtx->isWlanSuspended = FALSE;
1652
1653 /* Stop all the threads; we do not want any messages to be a processed,
1654 * any more and the best way to ensure that is to terminate the threads
1655 * gracefully.
1656 */
1657 /* Wait for MC to exit */
1658 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
1659 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
1660 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
1661 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
Mihir Shete165143a2013-12-19 09:06:13 +05301662 wait_for_completion(&vosSchedContext->McShutdown);
Jeff Johnson295189b2012-06-20 16:38:30 -07001663
1664 /* Wait for TX to exit */
1665 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
1666 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
1667 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
1668 wake_up_interruptible(&vosSchedContext->txWaitQueue);
Mihir Shete165143a2013-12-19 09:06:13 +05301669 wait_for_completion(&vosSchedContext->TxShutdown);
Jeff Johnson295189b2012-06-20 16:38:30 -07001670
1671 /* Wait for RX to exit */
1672 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
1673 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
1674 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
1675 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
Mihir Shete165143a2013-12-19 09:06:13 +05301676 wait_for_completion(&vosSchedContext->RxShutdown);
Jeff Johnson295189b2012-06-20 16:38:30 -07001677
1678#ifdef WLAN_BTAMP_FEATURE
1679 vosStatus = WLANBAP_Stop(pVosContext);
1680 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1681 {
1682 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1683 "%s: Failed to stop BAP",__func__);
1684 }
1685#endif //WLAN_BTAMP_FEATURE
1686 vosStatus = vos_wda_shutdown(pVosContext);
1687 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1688
1689 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
1690 /* Stop SME - Cannot invoke vos_stop as vos_stop relies
1691 * on threads being running to process the SYS Stop
1692 */
Kiet Lama72a2322013-11-15 11:18:11 +05301693 vosStatus = sme_Stop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
Jeff Johnson295189b2012-06-20 16:38:30 -07001694 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1695
1696 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
1697 /* Stop MAC (PE and HAL) */
1698 vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
1699 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1700
1701 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
1702 /* Stop TL */
1703 vosStatus = WLANTL_Stop(pVosContext);
1704 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1705
Jeff Johnson295189b2012-06-20 16:38:30 -07001706 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001707 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__);
1708 /* Clean up message queues of TX and MC thread */
1709 vos_sched_flush_mc_mqs(vosSchedContext);
1710 vos_sched_flush_tx_mqs(vosSchedContext);
1711 vos_sched_flush_rx_mqs(vosSchedContext);
1712
1713 /* Deinit all the TX and MC queues */
1714 vos_sched_deinit_mqs(vosSchedContext);
1715 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__);
1716
1717 /* shutdown VOSS */
1718 vos_shutdown(pVosContext);
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05301719
1720 /*mac context has already been released in mac_close call
1721 so setting it to NULL in hdd context*/
1722 pHddCtx->hHal = (tHalHandle)NULL;
1723
Jeff Johnson295189b2012-06-20 16:38:30 -07001724 if (free_riva_power_on_lock("wlan"))
1725 {
1726 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
1727 __func__);
1728 }
1729 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete"
1730 ,__func__);
1731 return VOS_STATUS_SUCCESS;
1732}
1733
1734
1735
1736/* the HDD interface to WLAN driver re-init.
1737 * This is called to initialize/start WLAN driver after a shutdown.
1738 */
1739VOS_STATUS hdd_wlan_re_init(void)
1740{
1741 VOS_STATUS vosStatus;
1742 v_CONTEXT_t pVosContext = NULL;
1743 hdd_context_t *pHddCtx = NULL;
1744 eHalStatus halStatus;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07001745#ifdef HAVE_WCNSS_CAL_DOWNLOAD
1746 int max_retries = 0;
1747#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001748#ifdef WLAN_BTAMP_FEATURE
1749 hdd_config_t *pConfig = NULL;
1750 WLANBAP_ConfigType btAmpConfig;
1751#endif
1752
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001753 hdd_ssr_timer_del();
Jeff Johnson295189b2012-06-20 16:38:30 -07001754 hdd_prevent_suspend();
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001755
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07001756#ifdef HAVE_WCNSS_CAL_DOWNLOAD
1757 /* wait until WCNSS driver downloads NV */
1758 while (!wcnss_device_ready() && 5 >= ++max_retries) {
1759 msleep(1000);
1760 }
1761 if (max_retries >= 5) {
1762 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
1763 goto err_re_init;
1764 }
1765#endif
1766
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07001767 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, TRUE);
1768
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001769 /* The driver should always be initialized in STA mode after SSR */
1770 hdd_set_conparam(0);
1771
Jeff Johnson295189b2012-06-20 16:38:30 -07001772 /* Re-open VOSS, it is a re-open b'se control transport was never closed. */
1773 vosStatus = vos_open(&pVosContext, 0);
1774 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1775 {
1776 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
1777 goto err_re_init;
1778 }
1779
1780 /* Get the HDD context. */
1781 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1782 if(!pHddCtx)
1783 {
1784 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1785 goto err_vosclose;
1786 }
1787
1788 /* Save the hal context in Adapter */
1789 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
1790 if ( NULL == pHddCtx->hHal )
1791 {
1792 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
1793 goto err_vosclose;
1794 }
1795
1796 /* Set the SME configuration parameters. */
1797 vosStatus = hdd_set_sme_config(pHddCtx);
1798 if ( VOS_STATUS_SUCCESS != vosStatus )
1799 {
1800 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
1801 goto err_vosclose;
1802 }
1803
1804 /* Initialize the WMM module */
1805 vosStatus = hdd_wmm_init(pHddCtx);
1806 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
1807 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001808 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001809 goto err_vosclose;
1810 }
1811
1812 vosStatus = vos_preStart( pHddCtx->pvosContext );
1813 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1814 {
1815 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
1816 goto err_vosclose;
1817 }
1818
1819 /* In the integrated architecture we update the configuration from
1820 the INI file and from NV before vOSS has been started so that
1821 the final contents are available to send down to the cCPU */
1822 /* Apply the cfg.ini to cfg.dat */
1823 if (FALSE == hdd_update_config_dat(pHddCtx))
1824 {
1825 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
1826 goto err_vosclose;
1827 }
1828
1829 /* Set the MAC Address, currently this is used by HAL to add self sta.
1830 * Remove this once self sta is added as part of session open. */
1831 halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID,
1832 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
1833 sizeof(pHddCtx->cfg_ini->intfMacAddr[0]));
1834 if (!HAL_STATUS_SUCCESS(halStatus))
1835 {
1836 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
1837 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus);
1838 goto err_vosclose;
1839 }
1840
1841 /* Start VOSS which starts up the SME/MAC/HAL modules and everything else
1842 Note: Firmware image will be read and downloaded inside vos_start API */
1843 vosStatus = vos_start( pVosContext );
1844 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1845 {
1846 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
1847 goto err_vosclose;
1848 }
1849
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07001850 /* Exchange capability info between Host and FW and also get versioning info from FW */
1851 hdd_exchange_version_and_caps(pHddCtx);
1852
Jeff Johnson295189b2012-06-20 16:38:30 -07001853 vosStatus = hdd_post_voss_start_config( pHddCtx );
1854 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1855 {
1856 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
1857 __func__);
1858 goto err_vosstop;
1859 }
1860
1861#ifdef WLAN_BTAMP_FEATURE
1862 vosStatus = WLANBAP_Open(pVosContext);
1863 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1864 {
1865 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1866 "%s: Failed to open BAP",__func__);
1867 goto err_vosstop;
1868 }
1869 vosStatus = BSL_Init(pVosContext);
1870 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1871 {
1872 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1873 "%s: Failed to Init BSL",__func__);
1874 goto err_bap_close;
1875 }
1876 vosStatus = WLANBAP_Start(pVosContext);
1877 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1878 {
1879 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1880 "%s: Failed to start TL",__func__);
1881 goto err_bap_close;
1882 }
1883 pConfig = pHddCtx->cfg_ini;
1884 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
1885 vosStatus = WLANBAP_SetConfig(&btAmpConfig);
1886#endif //WLAN_BTAMP_FEATURE
1887
1888 /* Restart all adapters */
1889 hdd_start_all_adapters(pHddCtx);
1890 pHddCtx->isLogpInProgress = FALSE;
Sameer Thalappilb511beb2013-09-09 17:11:51 -07001891 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001892 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001893 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001894
1895 /* Register with platform driver as client for Suspend/Resume */
1896 vosStatus = hddRegisterPmOps(pHddCtx);
1897 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1898 {
1899 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
1900 goto err_bap_stop;
1901 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001902 /* Allow the phone to go to sleep */
1903 hdd_allow_suspend();
1904 /* register for riva power on lock */
1905 if (req_riva_power_on_lock("wlan"))
1906 {
1907 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
1908 __func__);
1909 goto err_unregister_pmops;
1910 }
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07001911 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001912 goto success;
1913
1914err_unregister_pmops:
1915 hddDeregisterPmOps(pHddCtx);
1916
1917err_bap_stop:
Jeff Johnson32d95a32012-09-10 13:15:23 -07001918#ifdef CONFIG_HAS_EARLYSUSPEND
1919 hdd_unregister_mcast_bcast_filter(pHddCtx);
1920#endif
1921 hdd_close_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001922#ifdef WLAN_BTAMP_FEATURE
Jeff Johnson32d95a32012-09-10 13:15:23 -07001923 WLANBAP_Stop(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07001924#endif
1925
1926#ifdef WLAN_BTAMP_FEATURE
1927err_bap_close:
1928 WLANBAP_Close(pVosContext);
1929#endif
1930
1931err_vosstop:
1932 vos_stop(pVosContext);
1933
1934err_vosclose:
1935 vos_close(pVosContext);
1936 vos_sched_close(pVosContext);
1937 if (pHddCtx)
1938 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001939 /* Unregister the Net Device Notifier */
1940 unregister_netdevice_notifier(&hdd_netdev_notifier);
1941 /* Clean up HDD Nlink Service */
1942 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07001943#ifdef WLAN_KD_READY_NOTIFIER
1944 nl_srv_exit(pHddCtx->ptt_pid);
1945#else
Jeff Johnson295189b2012-06-20 16:38:30 -07001946 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07001947#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07001948 /* Free up dynamically allocated members inside HDD Adapter */
1949 kfree(pHddCtx->cfg_ini);
1950 pHddCtx->cfg_ini= NULL;
1951
Jeff Johnson295189b2012-06-20 16:38:30 -07001952 wiphy_unregister(pHddCtx->wiphy);
1953 wiphy_free(pHddCtx->wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07001954 }
1955 vos_preClose(&pVosContext);
1956
1957#ifdef MEMORY_DEBUG
1958 vos_mem_exit();
1959#endif
1960
1961err_re_init:
1962 /* Allow the phone to go to sleep */
1963 hdd_allow_suspend();
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07001964 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07001965 VOS_BUG(0);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001966 return -EPERM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001967
1968success:
1969 /* Trigger replay of BTC events */
1970 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1971 return VOS_STATUS_SUCCESS;
1972}