blob: d08a1816d0a57dd31dcce8423e6208a02b321b5c [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Vinay Krishna Eranna55029602015-02-06 15:43:35 +05302 * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
Kiet Lam842dad02014-02-18 18:44:02 -08003 *
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.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080020 */
Kiet Lam842dad02014-02-18 18:44:02 -080021
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
Jeff Johnson295189b2012-06-20 16:38:30 -070028/**=============================================================================
29* wlan_hdd_early_suspend.c
30*
31* \brief power management functions
32*
33* Description
Jeff Johnson295189b2012-06-20 16:38:30 -070034*
35==============================================================================**/
36/* $HEADER$ */
37
38/**-----------------------------------------------------------------------------
39* Include files
40* ----------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -070041
42#include <linux/pm.h>
43#include <linux/wait.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070044#include <wlan_hdd_includes.h>
45#include <wlan_qct_driver.h>
46#include <linux/wakelock.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070047
48#include "halTypes.h"
49#include "sme_Api.h"
50#include <vos_api.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070051#include <vos_sched.h>
52#include <macInitApi.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070053#include <wlan_qct_sys.h>
54#include <wlan_btc_svc.h>
55#include <wlan_nlink_common.h>
56#include <wlan_hdd_main.h>
57#include <wlan_hdd_assoc.h>
58#include <wlan_hdd_dev_pwr.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070059#include <wlan_nlink_srv.h>
60#include <wlan_hdd_misc.h>
Amar Singhald08ce752014-03-21 16:28:27 -070061#include "wlan_qct_wda.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070062
Jeff Johnson295189b2012-06-20 16:38:30 -070063#include <linux/semaphore.h>
64#include <wlan_hdd_hostapd.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070065#include "cfgApi.h"
Siddharth Bhal7bd19932015-03-03 16:54:36 +053066#include <wlan_logging_sock_svc.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070067
68#ifdef WLAN_BTAMP_FEATURE
69#include "bapApi.h"
70#include "bap_hdd_main.h"
71#include "bap_hdd_misc.h"
72#endif
73
Jeff Johnsone7245742012-09-05 17:12:55 -070074#include <linux/wcnss_wlan.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070075#include <linux/inetdevice.h>
76#include <wlan_hdd_cfg.h>
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053077#include <wlan_hdd_cfg80211.h>
Gopichand Nakkala746a9452013-06-11 12:45:54 +053078#include <net/addrconf.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070079/**-----------------------------------------------------------------------------
80* Preprocessor definitions and constants
81* ----------------------------------------------------------------------------*/
82
83/**-----------------------------------------------------------------------------
84* Type declarations
85* ----------------------------------------------------------------------------*/
86
87/**-----------------------------------------------------------------------------
88* Function and variables declarations
89* ----------------------------------------------------------------------------*/
90#include "wlan_hdd_power.h"
91#include "wlan_hdd_packet_filtering.h"
92
Sameer Thalappile5637f42013-08-07 15:46:55 -070093#define HDD_SSR_BRING_UP_TIME 180000
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +053094#define NS_DEFAULT_SLOT_INDEX 4
95#define NS_EXTENDED_SLOT_INDEX 18
Jeff Johnson295189b2012-06-20 16:38:30 -070096
97static eHalStatus g_full_pwr_status;
98static eHalStatus g_standby_status;
99
100extern VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700101extern void hdd_wlan_initial_scan(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700102
103extern struct notifier_block hdd_netdev_notifier;
Jeff Johnson295189b2012-06-20 16:38:30 -0700104extern tVOS_CON_MODE hdd_get_conparam ( void );
Jeff Johnson295189b2012-06-20 16:38:30 -0700105
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -0700106static struct timer_list ssr_timer;
107static bool ssr_timer_started;
Jeff Johnson295189b2012-06-20 16:38:30 -0700108
109//Callback invoked by PMC to report status of standby request
110void hdd_suspend_standby_cbk (void *callbackContext, eHalStatus status)
111{
112 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
113 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Standby status = %d", __func__, status);
114 g_standby_status = status;
115
116 if(eHAL_STATUS_SUCCESS == status)
117 {
118 pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY;
119 }
120 else
121 {
122 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__);
123 }
124
125 complete(&pHddCtx->standby_comp_var);
126}
127
128//Callback invoked by PMC to report status of full power request
129void hdd_suspend_full_pwr_callback(void *callbackContext, eHalStatus status)
130{
131 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
132 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Full Power status = %d", __func__, status);
133 g_full_pwr_status = status;
134
135 if(eHAL_STATUS_SUCCESS == status)
136 {
137 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
138 }
139 else
140 {
141 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
142 }
143
144 complete(&pHddCtx->full_pwr_comp_var);
145}
146
147eHalStatus hdd_exit_standby(hdd_context_t *pHddCtx)
148{
149 eHalStatus status = VOS_STATUS_SUCCESS;
c_hpothuffdb5272013-10-02 16:42:35 +0530150 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -0700151
152 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from standby",__func__);
153 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
154
155 g_full_pwr_status = eHAL_STATUS_FAILURE;
156 status = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback, pHddCtx,
157 eSME_FULL_PWR_NEEDED_BY_HDD);
158
159 if(status == eHAL_STATUS_PMC_PENDING)
160 {
161 //Block on a completion variable. Can't wait forever though
c_hpothuffdb5272013-10-02 16:42:35 +0530162 ret = wait_for_completion_interruptible_timeout(
163 &pHddCtx->full_pwr_comp_var,
164 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
165 if (0 >= ret)
166 {
167 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:wait on full_pwr_comp_var failed %ld",
168 __func__, ret);
169 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700170 status = g_full_pwr_status;
171 if(g_full_pwr_status != eHAL_STATUS_SUCCESS)
172 {
173 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
174 VOS_ASSERT(0);
175 goto failure;
176 }
177 }
178 else if(status != eHAL_STATUS_SUCCESS)
179 {
180 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d",
181 __func__, status);
182 VOS_ASSERT(0);
183 goto failure;
184 }
185 else
186 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
187
188failure:
189 //No blocking to reduce latency. No other device should be depending on WLAN
190 //to finish resume and WLAN won't be instantly on after resume
191 return status;
192}
193
194
195//Helper routine to put the chip into standby
196VOS_STATUS hdd_enter_standby(hdd_context_t *pHddCtx)
197{
198 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
199 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
c_hpothuffdb5272013-10-02 16:42:35 +0530200 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -0700201
202 //Disable IMPS/BMPS as we do not want the device to enter any power
203 //save mode on its own during suspend sequence
204 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
205 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
206
207 //Note we do not disable queues unnecessarily. Queues should already be disabled
208 //if STA is disconnected or the queue will be disabled as and when disconnect
209 //happens because of standby procedure.
210
211 //Ensure that device is in full power first. There is scope for optimization
212 //here especially in scenarios where PMC is already in IMPS or REQUEST_IMPS.
213 //Core s/w needs to be optimized to handle this. Until then we request full
214 //power before issuing request for standby.
215 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
216 g_full_pwr_status = eHAL_STATUS_FAILURE;
217 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback,
218 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
219
220 if(halStatus == eHAL_STATUS_PMC_PENDING)
221 {
222 //Block on a completion variable. Can't wait forever though
c_hpothuffdb5272013-10-02 16:42:35 +0530223 ret = wait_for_completion_interruptible_timeout(
224 &pHddCtx->full_pwr_comp_var,
225 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
226 if (0 >= ret)
227 {
228 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:wait on full_pwr_comp_var failed %ld",
229 __func__, ret);
230 }
231
Jeff Johnson295189b2012-06-20 16:38:30 -0700232 if(g_full_pwr_status != eHAL_STATUS_SUCCESS)
233 {
234 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower Failed",__func__);
235 VOS_ASSERT(0);
236 vosStatus = VOS_STATUS_E_FAILURE;
237 goto failure;
238 }
239 }
240 else if(halStatus != eHAL_STATUS_SUCCESS)
241 {
242 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d",
243 __func__, halStatus);
244 VOS_ASSERT(0);
245 vosStatus = VOS_STATUS_E_FAILURE;
246 goto failure;
247 }
248
249 if(pHddCtx->hdd_mcastbcast_filter_set == TRUE) {
250 hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
251 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
252 }
253
254 //Request standby. Standby will cause the STA to disassociate first. TX queues
255 //will be disabled (by HDD) when STA disconnects. You do not want to disable TX
256 //queues here. Also do not assert if the failure code is eHAL_STATUS_PMC_NOT_NOW as PMC
257 //will send this failure code in case of concurrent sessions. Power Save cannot be supported
258 //when there are concurrent sessions.
259 INIT_COMPLETION(pHddCtx->standby_comp_var);
260 g_standby_status = eHAL_STATUS_FAILURE;
261 halStatus = sme_RequestStandby(pHddCtx->hHal, hdd_suspend_standby_cbk, pHddCtx);
262
263 if (halStatus == eHAL_STATUS_PMC_PENDING)
264 {
265 //Wait till WLAN device enters standby mode
c_hpothuffdb5272013-10-02 16:42:35 +0530266 ret = wait_for_completion_timeout(&pHddCtx->standby_comp_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700267 msecs_to_jiffies(WLAN_WAIT_TIME_STANDBY));
c_hpothuffdb5272013-10-02 16:42:35 +0530268 if (0 >= ret)
269 {
270 hddLog(VOS_TRACE_LEVEL_ERROR,
271 FL("wait on standby_comp_var failed %ld"), ret);
272 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700273 if (g_standby_status != eHAL_STATUS_SUCCESS && g_standby_status != eHAL_STATUS_PMC_NOT_NOW)
274 {
275 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__);
276 VOS_ASSERT(0);
277 vosStatus = VOS_STATUS_E_FAILURE;
278 goto failure;
279 }
280 }
281 else if (halStatus != eHAL_STATUS_SUCCESS && halStatus != eHAL_STATUS_PMC_NOT_NOW) {
282 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed - status %d",
283 __func__, halStatus);
284 VOS_ASSERT(0);
285 vosStatus = VOS_STATUS_E_FAILURE;
286 goto failure;
287 }
288 else
289 pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY;
290
291failure:
292 //Restore IMPS config
293 if(pHddCtx->cfg_ini->fIsImpsEnabled)
294 sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
295
296 //Restore BMPS config
297 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
298 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
299
300 return vosStatus;
301}
302
303
304//Helper routine for Deep sleep entry
305VOS_STATUS hdd_enter_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter)
306{
307 eHalStatus halStatus;
308 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
c_hpothuffdb5272013-10-02 16:42:35 +0530309 long ret;
Jeff Johnsonbc676b42013-02-14 16:04:08 -0800310
Jeff Johnson295189b2012-06-20 16:38:30 -0700311 //Stop the Interface TX queue.
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +0530312 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -0700313 netif_tx_disable(pAdapter->dev);
314 netif_carrier_off(pAdapter->dev);
315
316 //Disable IMPS,BMPS as we do not want the device to enter any power
317 //save mode on it own during suspend sequence
318 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
319 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
320
321 //Ensure that device is in full power as we will touch H/W during vos_Stop
322 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
323 g_full_pwr_status = eHAL_STATUS_FAILURE;
324 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback,
325 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
326
327 if(halStatus == eHAL_STATUS_PMC_PENDING)
328 {
329 //Block on a completion variable. Can't wait forever though
c_hpothuffdb5272013-10-02 16:42:35 +0530330 ret = wait_for_completion_interruptible_timeout(
331 &pHddCtx->full_pwr_comp_var,
332 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
333 if (0 >= ret)
334 {
335 hddLog(VOS_TRACE_LEVEL_ERROR,
336 FL("wait on full_pwr_comp_var failed %ld"), ret);
337 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700338 if(g_full_pwr_status != eHAL_STATUS_SUCCESS){
339 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
340 VOS_ASSERT(0);
341 }
342 }
343 else if(halStatus != eHAL_STATUS_SUCCESS)
344 {
345 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Request for Full Power failed",__func__);
346 VOS_ASSERT(0);
347 }
348
349 //Issue a disconnect. This is required to inform the supplicant that
350 //STA is getting disassociated and for GUI to be updated properly
351 INIT_COMPLETION(pAdapter->disconnect_comp_var);
352 halStatus = sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED);
353
354 //Success implies disconnect command got queued up successfully
355 if(halStatus == eHAL_STATUS_SUCCESS)
356 {
357 //Block on a completion variable. Can't wait forever though.
c_hpothuffdb5272013-10-02 16:42:35 +0530358 ret = wait_for_completion_interruptible_timeout(
359 &pAdapter->disconnect_comp_var,
360 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
361 if (0 >= ret)
362 {
363 hddLog(VOS_TRACE_LEVEL_ERROR,
364 FL("wait on disconnect_comp_var failed %ld"), ret);
365 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700366 }
367
368
369 //None of the steps should fail after this. Continue even in case of failure
370 vosStatus = vos_stop( pHddCtx->pvosContext );
c_hpothuffdb5272013-10-02 16:42:35 +0530371 if( !VOS_IS_STATUS_SUCCESS( vosStatus ))
372 {
373 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: vos_stop return failed %d",
374 __func__, vosStatus);
375 VOS_ASSERT(0);
376 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700377
Jeff Johnson295189b2012-06-20 16:38:30 -0700378 pHddCtx->hdd_ps_state = eHDD_SUSPEND_DEEP_SLEEP;
379
380 //Restore IMPS config
381 if(pHddCtx->cfg_ini->fIsImpsEnabled)
382 sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
383
384 //Restore BMPS config
385 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
386 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
387
Jeff Johnson295189b2012-06-20 16:38:30 -0700388 return vosStatus;
389}
390
391VOS_STATUS hdd_exit_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter)
392{
393 VOS_STATUS vosStatus;
394 eHalStatus halStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -0700395
Jeff Johnson295189b2012-06-20 16:38:30 -0700396 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
397 "%s: calling hdd_set_sme_config",__func__);
398 vosStatus = hdd_set_sme_config( pHddCtx );
399 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
400 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
401 {
402 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
403 "%s: Failed in hdd_set_sme_config",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700404 goto err_deep_sleep;
Jeff Johnson295189b2012-06-20 16:38:30 -0700405 }
406
407 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
408 "%s: calling vos_start",__func__);
409 vosStatus = vos_start( pHddCtx->pvosContext );
410 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
411 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
412 {
413 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
414 "%s: Failed in vos_start",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700415 goto err_deep_sleep;
Jeff Johnson295189b2012-06-20 16:38:30 -0700416 }
417
418 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
419 "%s: calling hdd_post_voss_start_config",__func__);
420 vosStatus = hdd_post_voss_start_config( pHddCtx );
421 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
422 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
423 {
424 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
425 "%s: Failed in hdd_post_voss_start_config",__func__);
426 goto err_voss_stop;
427 }
428
429
430 //Open a SME session for future operation
431 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pHddCtx,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -0700432 (tANI_U8 *)&pAdapter->macAddressCurrent,
433 &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700434 if ( !HAL_STATUS_SUCCESS( halStatus ) )
435 {
Jeff Johnson0299d0a2013-10-30 12:37:43 -0700436 hddLog(VOS_TRACE_LEVEL_FATAL,"sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -0700437 halStatus, halStatus );
438 goto err_voss_stop;
439
440 }
441
442 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
443
444 //Trigger the initial scan
445 hdd_wlan_initial_scan(pHddCtx);
446
447 return VOS_STATUS_SUCCESS;
448
449err_voss_stop:
450 vos_stop(pHddCtx->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -0700451err_deep_sleep:
452 return VOS_STATUS_E_FAILURE;
453
454}
455
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530456void __hdd_ipv6_notifier_work_queue(struct work_struct *work)
Atul Mittal37385d72014-03-27 18:15:03 +0530457{
458 hdd_adapter_t* pAdapter =
459 container_of(work, hdd_adapter_t, ipv6NotifierWorkQueue);
460 hdd_context_t *pHddCtx;
461 int status;
462
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530463 ENTER();
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530464 if (NULL == pAdapter)
465 {
466 hddLog(LOGE, FL("Adapter is invalid"));
467 return;
468 }
Atul Mittal37385d72014-03-27 18:15:03 +0530469
470 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
471 status = wlan_hdd_validate_context(pHddCtx);
472 if (0 != status)
473 {
Atul Mittal37385d72014-03-27 18:15:03 +0530474 return;
475 }
476
477 if ( VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid)
478 {
479 pHddCtx->sus_res_mcastbcast_filter =
480 pHddCtx->configuredMcastBcastFilter;
Sushant Kaushik439d4c72014-05-12 16:39:51 +0530481 hddLog(LOG1, FL("saving configuredMcastBcastFilter = %d"),
482 pHddCtx->sus_res_mcastbcast_filter);
Atul Mittal37385d72014-03-27 18:15:03 +0530483 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
484 }
485
486 if ((eConnectionState_Associated ==
487 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)
488 && (pHddCtx->hdd_wlan_suspended))
489 {
490 // This invocation being part of the IPv6 registration callback,
491 // set the newly generated ip address to f/w in suspend mode.
492#ifdef WLAN_NS_OFFLOAD
Vinay Krishna Eranna83b0ef72014-11-19 16:56:20 +0530493 if (pHddCtx->cfg_ini->fhostNSOffload)
494 {
495 hdd_conf_ns_offload(pAdapter, 1);
496 }
Atul Mittal37385d72014-03-27 18:15:03 +0530497#endif
498 }
499#ifdef WLAN_FEATURE_PACKET_FILTERING
Vinay Krishna Eranna83b0ef72014-11-19 16:56:20 +0530500 /* wlan_hdd_set_mc_addr_list() is called from the early suspend
Atul Mittal37385d72014-03-27 18:15:03 +0530501 * only so when new ipv6 address is generated the screen may not
502 * on so we need to call it here to update the list in f/w.
503 */
Vinay Krishna Eranna83b0ef72014-11-19 16:56:20 +0530504 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
Atul Mittal37385d72014-03-27 18:15:03 +0530505#endif
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530506 EXIT();
Atul Mittal37385d72014-03-27 18:15:03 +0530507}
508
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530509void hdd_ipv6_notifier_work_queue(struct work_struct *work)
510{
511 vos_ssr_protect(__func__);
512 __hdd_ipv6_notifier_work_queue(work);
513 vos_ssr_unprotect(__func__);
514}
Mukul Sharmaa78cf6b2015-02-24 16:59:01 +0530515int __wlan_hdd_ipv6_changed(struct notifier_block *nb,
Vinay Krishna Eranna83b0ef72014-11-19 16:56:20 +0530516 unsigned long data, void *arg)
Atul Mittal37385d72014-03-27 18:15:03 +0530517{
518 struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)arg;
519 struct net_device *ndev = ifa->idev->dev;
Vinay Krishna Eranna55029602015-02-06 15:43:35 +0530520 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Atul Mittal37385d72014-03-27 18:15:03 +0530521 hdd_context_t *pHddCtx;
Vinay Krishna Eranna55029602015-02-06 15:43:35 +0530522 VOS_STATUS vos_status;
Atul Mittal37385d72014-03-27 18:15:03 +0530523 int status;
524
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530525 ENTER();
Vinay Krishna Eranna55029602015-02-06 15:43:35 +0530526 pHddCtx = container_of(nb, hdd_context_t, ipv6_notifier);
527 status = wlan_hdd_validate_context(pHddCtx);
528 if (0 != status)
Atul Mittal37385d72014-03-27 18:15:03 +0530529 {
Vinay Krishna Eranna55029602015-02-06 15:43:35 +0530530 return NOTIFY_DONE;
531 }
Atul Mittal37385d72014-03-27 18:15:03 +0530532
Vinay Krishna Eranna55029602015-02-06 15:43:35 +0530533 vos_status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
534 while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == vos_status)
535 {
536 if (pAdapterNode->pAdapter && pAdapterNode->pAdapter->dev == ndev &&
537 (pAdapterNode->pAdapter->device_mode == WLAN_HDD_INFRA_STATION ||
538 pAdapterNode->pAdapter->device_mode == WLAN_HDD_P2P_CLIENT))
539 {
540 if (pHddCtx->cfg_ini->nEnableSuspend ==
Vinay Krishna Eranna83b0ef72014-11-19 16:56:20 +0530541 WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER)
Vinay Krishna Eranna55029602015-02-06 15:43:35 +0530542 {
543 schedule_work(&pAdapterNode->pAdapter->ipv6NotifierWorkQueue);
544 }
545 else
546 {
547 hddLog(LOG1, FL("Not scheduling ipv6 wq nEnableSuspend = %d"),
548 pHddCtx->cfg_ini->nEnableSuspend);
549 }
550 break;
551 }
552 vos_status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
553 pAdapterNode = pNext;
Atul Mittal37385d72014-03-27 18:15:03 +0530554 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530555 EXIT();
Atul Mittal37385d72014-03-27 18:15:03 +0530556 return NOTIFY_DONE;
557}
558
Mukul Sharmaa78cf6b2015-02-24 16:59:01 +0530559int wlan_hdd_ipv6_changed(struct notifier_block *nb,
560 unsigned long data, void *arg)
561{
562 int ret;
563 vos_ssr_protect(__func__);
564 ret = __wlan_hdd_ipv6_changed( nb, data, arg);
565 vos_ssr_unprotect(__func__);
566 return ret;
567}
568
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530569/*
570 * Function: hdd_conf_hostoffload
571 * Central function to configure the supported offloads,
572 * either enable or disable them.
573 */
574void hdd_conf_hostoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
575{
576 hdd_context_t *pHddCtx = NULL;
577 v_CONTEXT_t *pVosContext = NULL;
578 VOS_STATUS vstatus = VOS_STATUS_E_FAILURE;
579
580 hddLog(VOS_TRACE_LEVEL_INFO, FL("Configuring offloads with flag: %d"),
581 fenable);
582
583 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
584
585 if (NULL == pVosContext)
586 {
587 hddLog(VOS_TRACE_LEVEL_ERROR, FL(" Global VOS context is Null"));
588 return;
589 }
590
591 //Get the HDD context.
592 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
593
594 if (NULL == pHddCtx)
595 {
596 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: HDD context is Null", __func__);
597 return;
598 }
599
600 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
601 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
602 {
603 if (fenable)
604 {
605 if (eConnectionState_Associated ==
606 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)
607 {
608 if ((pHddCtx->cfg_ini->fhostArpOffload))
609 {
610 /*
611 * Configure the ARP Offload.
612 * Even if it fails we have to reconfigure the MC/BC
613 * filter flag as we want RIVA not to drop BroadCast
614 * Packets
615 */
616 hddLog(VOS_TRACE_LEVEL_INFO,
617 FL("Calling ARP Offload with flag: %d"), fenable);
618 vstatus = hdd_conf_arp_offload(pAdapter, fenable);
619 pHddCtx->configuredMcastBcastFilter &=
620 ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST);
621
622 if (!VOS_IS_STATUS_SUCCESS(vstatus))
623 {
624 hddLog(VOS_TRACE_LEVEL_ERROR,
625 "Failed to enable ARPOFfloadFeature %d",
626 vstatus);
627 }
628 }
629 //Configure GTK_OFFLOAD
630#ifdef WLAN_FEATURE_GTK_OFFLOAD
631 hdd_conf_gtk_offload(pAdapter, fenable);
632#endif
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530633
634#ifdef WLAN_NS_OFFLOAD
635 if (pHddCtx->cfg_ini->fhostNSOffload)
636 {
637 /*
638 * Configure the NS Offload.
639 * Even if it fails we have to reconfigure the MC/BC filter flag
640 * as we want RIVA not to drop Multicast Packets
641 */
642
643 hddLog(VOS_TRACE_LEVEL_INFO,
644 FL("Calling NS Offload with flag: %d"), fenable);
645 hdd_conf_ns_offload(pAdapter, fenable);
646 pHddCtx->configuredMcastBcastFilter &=
647 ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST);
648 }
649#endif
Atul Mittal37385d72014-03-27 18:15:03 +0530650
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530651 }
652 }
653 else
654 {
655 //Disable ARPOFFLOAD
656 if (pHddCtx->cfg_ini->fhostArpOffload)
657 {
658 vstatus = hdd_conf_arp_offload(pAdapter, fenable);
659 if (!VOS_IS_STATUS_SUCCESS(vstatus))
660 {
661 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530662 "Failed to disable ARPOffload Feature %d", vstatus);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530663 }
664 }
665 //Disable GTK_OFFLOAD
666#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530667 hdd_conf_gtk_offload(pAdapter, fenable);
668#endif
669
670#ifdef WLAN_NS_OFFLOAD
671 //Disable NSOFFLOAD
672 if (pHddCtx->cfg_ini->fhostNSOffload)
673 {
674 hdd_conf_ns_offload(pAdapter, fenable);
675 }
Gopichand Nakkalab03e8082013-05-30 18:09:25 +0530676#endif
677 }
678 }
679 return;
680}
681
Atul Mittal37385d72014-03-27 18:15:03 +0530682
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530683#ifdef WLAN_NS_OFFLOAD
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +0530684/**----------------------------------------------------------------------------
685
686 \brief hdd_conf_ns_offload() - Configure NS offload
687
688 Called during SUSPEND to configure the NS offload (MC BC filter) which
689 reduces power consumption.
690
691 \param - pAdapter - Adapter context for which NS offload is to be configured
692 \param - fenable - 0 - disable.
693 1 - enable. (with IPv6 notifier registration)
694 2 - enable. (without IPv6 notifier registration)
695
696 \return - void
697
698 ---------------------------------------------------------------------------*/
699void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, int fenable)
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530700{
701 struct inet6_dev *in6_dev;
702 struct inet6_ifaddr *ifp;
703 struct list_head *p;
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530704 int slot_index = NS_DEFAULT_SLOT_INDEX;
Girish Gowli1b6114f2014-05-17 17:17:09 +0530705 tANI_U8 **selfIPv6Addr = NULL;
706 tANI_U8 *selfIPv6AddrValid = NULL;
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530707 tSirHostOffloadReq offLoadRequest;
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530708 hdd_context_t *pHddCtx;
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530709 tHalHandle halHandle;
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530710
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530711 int i = 0, slot = 0;
712 int ret = 0;
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530713 eHalStatus returnStatus;
714
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +0530715 ENTER();
716 hddLog(LOG1, FL(" fenable = %d"), fenable);
717
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530718 if (NULL == pAdapter)
719 {
720 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD adapter is Null"));
721 return;
722 }
723
724 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530725 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
726
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530727 ret = wlan_hdd_validate_context(pHddCtx);
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530728 if (0 != ret)
729 {
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530730 return;
731 }
732
733 if (sme_IsFeatureSupportedByFW(EXTENDED_NSOFFLOAD_SLOT))
734 {
735 slot_index = NS_EXTENDED_SLOT_INDEX;
736 }
737
738 hddLog(VOS_TRACE_LEVEL_INFO, FL("slot_idex = %d"), slot_index);
739
740 selfIPv6AddrValid =
741 (tANI_U8 *)vos_mem_malloc(sizeof(tANI_U8) * slot_index);
742
743 if (NULL == selfIPv6AddrValid)
744 {
745 hddLog (VOS_TRACE_LEVEL_ERROR, FL("Failed to allocate memory for"
746 " selfIPv6AddrValid"));
747 goto end;
748 }
749
750 vos_mem_zero(selfIPv6AddrValid, slot_index * sizeof(tANI_U8));
751
752 selfIPv6Addr = (tANI_U8 **)vos_mem_malloc(sizeof(tANI_U8 *) * slot_index);
753
754 if (NULL == selfIPv6Addr)
755 {
756 hddLog (VOS_TRACE_LEVEL_ERROR, FL("Failed to allocate memory for"
757 " selfIPv6Addr"));
758 goto end;
759 }
760
761 vos_mem_zero(selfIPv6Addr, slot_index * sizeof(tANI_U8 *));
762
763 for (slot = 0; slot < slot_index; slot++)
764 {
765 selfIPv6Addr[slot] =
766 (tANI_U8 *)vos_mem_malloc(SIR_MAC_IPV6_ADDR_LEN);
767 if (NULL == selfIPv6Addr[slot])
768 {
769 hddLog (VOS_TRACE_LEVEL_ERROR, FL("Failed to allocate memory"
770 "for selfIPv6Addr"));
771 goto end;
772 }
773 vos_mem_zero(selfIPv6Addr[slot], SIR_MAC_IPV6_ADDR_LEN);
774 }
775
776 i = 0;
777
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530778 if (fenable)
779 {
780 in6_dev = __in6_dev_get(pAdapter->dev);
781 if (NULL != in6_dev)
782 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530783 list_for_each(p, &in6_dev->addr_list)
784 {
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530785 if (i >= slot_index)
786 {
787 hddLog (VOS_TRACE_LEVEL_ERROR,
788 FL("IPv6 address list is greater than IPv6"
789 "address supported by firmware"));
790 hddLog (VOS_TRACE_LEVEL_ERROR,
791 FL("FW supported IPv6 address = %d"), slot_index);
792 break;
793 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530794 ifp = list_entry(p, struct inet6_ifaddr, if_list);
795 switch(ipv6_addr_src_scope(&ifp->addr))
796 {
797 case IPV6_ADDR_SCOPE_LINKLOCAL:
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530798 vos_mem_copy(selfIPv6Addr[i], &ifp->addr.s6_addr,
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530799 sizeof(ifp->addr.s6_addr));
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530800 selfIPv6AddrValid[i] = SIR_IPV6_ADDR_VALID;
Hardik Kantilal Patel1341bdf2013-08-22 20:27:15 +0530801 hddLog (VOS_TRACE_LEVEL_INFO,
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530802 FL("Found IPV6_ADDR_SCOPE_LINKLOCAL Address : %pI6"),
803 selfIPv6Addr[i]);
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530804 break;
805 case IPV6_ADDR_SCOPE_GLOBAL:
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530806 vos_mem_copy(selfIPv6Addr[i], &ifp->addr.s6_addr,
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530807 sizeof(ifp->addr.s6_addr));
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530808 selfIPv6AddrValid[i] = SIR_IPV6_ADDR_VALID;
Hardik Kantilal Patel1341bdf2013-08-22 20:27:15 +0530809 hddLog (VOS_TRACE_LEVEL_INFO,
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530810 FL("Found IPV6_ADDR_SCOPE_GLOBAL Address : %pI6"),
811 selfIPv6Addr[i]);
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530812 break;
813 default:
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530814 hddLog(VOS_TRACE_LEVEL_ERROR,
815 FL("The Scope %d is not supported"),
816 ipv6_addr_src_scope(&ifp->addr));
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530817 }
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530818 if (selfIPv6AddrValid[i] == SIR_IPV6_ADDR_VALID)
819 {
820 i++;
821 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530822 }
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530823
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530824 vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest));
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530825 for (i =0; i < slot_index; i++)
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530826 {
827 if (selfIPv6AddrValid[i])
828 {
829 //Filling up the request structure
830 /* Filling the selfIPv6Addr with solicited address
831 * A Solicited-Node multicast address is created by
832 * taking the last 24 bits of a unicast or anycast
833 * address and appending them to the prefix
834 *
835 * FF02:0000:0000:0000:0000:0001:FFXX:XX
836 *
837 * here XX is the unicast/anycast bits
838 */
839 offLoadRequest.nsOffloadInfo.selfIPv6Addr[0] = 0xFF;
840 offLoadRequest.nsOffloadInfo.selfIPv6Addr[1] = 0x02;
841 offLoadRequest.nsOffloadInfo.selfIPv6Addr[11] = 0x01;
842 offLoadRequest.nsOffloadInfo.selfIPv6Addr[12] = 0xFF;
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530843 offLoadRequest.nsOffloadInfo.selfIPv6Addr[13] =
844 selfIPv6Addr[i][13];
845 offLoadRequest.nsOffloadInfo.selfIPv6Addr[14] =
846 selfIPv6Addr[i][14];
847 offLoadRequest.nsOffloadInfo.selfIPv6Addr[15] =
848 selfIPv6Addr[i][15];
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530849 offLoadRequest.nsOffloadInfo.slotIdx = i;
850
851 vos_mem_copy(&offLoadRequest.nsOffloadInfo.targetIPv6Addr[0],
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530852 selfIPv6Addr[i], sizeof(tANI_U8)*SIR_MAC_IPV6_ADDR_LEN);
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530853 vos_mem_copy(&offLoadRequest.nsOffloadInfo.selfMacAddr,
854 &pAdapter->macAddressCurrent.bytes,
855 sizeof(tANI_U8)*SIR_MAC_ADDR_LEN);
856
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530857 offLoadRequest.nsOffloadInfo.targetIPv6AddrValid[0] =
858 SIR_IPV6_ADDR_VALID;
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530859 offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD;
860 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
861
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530862 hddLog (VOS_TRACE_LEVEL_INFO,
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530863 FL("configuredMcastBcastFilter: %d"
864 "NSOffload Slot = %d"),
865 pHddCtx->configuredMcastBcastFilter, i);
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530866
Kiet Lamc8e1eb52013-10-24 00:30:49 +0530867 if ((VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid)
Amar Singhald08ce752014-03-21 16:28:27 -0700868 && ((HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST ==
869 pHddCtx->sus_res_mcastbcast_filter) ||
870 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
871 pHddCtx->sus_res_mcastbcast_filter)) &&
872 (!WDA_IS_MCAST_FLT_ENABLE_IN_FW ||
873 (WDA_IS_MCAST_FLT_ENABLE_IN_FW &&
874 !(pHddCtx->cfg_ini->fEnableMCAddrList))))
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530875 {
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530876 offLoadRequest.enableOrDisable =
Amar Singhald08ce752014-03-21 16:28:27 -0700877 SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE;
Sushant Kaushik439d4c72014-05-12 16:39:51 +0530878 hddLog (VOS_TRACE_LEVEL_INFO,
879 FL("Set offLoadRequest with %d"),
880 offLoadRequest.enableOrDisable);
Madan Mohan Koyyalamudibadffe72013-09-11 13:09:14 +0530881 }
882
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530883 vos_mem_copy(&offLoadRequest.params.hostIpv6Addr,
884 &offLoadRequest.nsOffloadInfo.targetIPv6Addr[0],
885 sizeof(tANI_U8)*SIR_MAC_IPV6_ADDR_LEN);
886
887 hddLog (VOS_TRACE_LEVEL_INFO,
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530888 FL("Setting NSOffload with solicitedIp: %pI6,"
889 "targetIp: %pI6"),
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530890 offLoadRequest.nsOffloadInfo.selfIPv6Addr,
891 offLoadRequest.nsOffloadInfo.targetIPv6Addr[0]);
892
893 //Configure the Firmware with this
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530894 returnStatus = sme_SetHostOffload(halHandle,
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530895 pAdapter->sessionId, &offLoadRequest);
896 if(eHAL_STATUS_SUCCESS != returnStatus)
897 {
898 hddLog(VOS_TRACE_LEVEL_ERROR,
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530899 FL("Failed to enable HostOffload feature with"
900 " status: %d"), returnStatus);
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530901 }
902 vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest));
903 }
904 }
905 }
906 else
907 {
908 hddLog(VOS_TRACE_LEVEL_ERROR,
909 FL("IPv6 dev does not exist. Failed to request NSOffload"));
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530910 goto end;
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530911 }
912 }
913 else
914 {
915 //Disable NSOffload
916 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
917 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
918 offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD;
919
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530920 for (i = 0; i < slot_index; i++)
Vinay Krishna Erannab29c6142014-01-07 12:20:51 +0530921 {
c_hpothu86feba52014-10-28 15:51:18 +0530922 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disable Slot= %d"), i);
Vinay Krishna Erannab29c6142014-01-07 12:20:51 +0530923 offLoadRequest.nsOffloadInfo.slotIdx = i;
924 if (eHAL_STATUS_SUCCESS !=
Vinay Krishna Eranna911a3b82014-01-07 12:20:51 +0530925 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
926 pAdapter->sessionId, &offLoadRequest))
Vinay Krishna Erannab29c6142014-01-07 12:20:51 +0530927 {
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530928 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failure to disable"
929 " %d Slot"), i);
Vinay Krishna Erannab29c6142014-01-07 12:20:51 +0530930 }
931 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530932 }
Hardik Kantilal Patele1760e12014-01-21 15:57:21 +0530933end:
934 while (slot > 0 && selfIPv6Addr[--slot])
935 {
936 vos_mem_free(selfIPv6Addr[slot]);
937 }
938 if (selfIPv6Addr)
939 {
940 vos_mem_free(selfIPv6Addr);
941 }
942 if (selfIPv6AddrValid)
943 {
944 vos_mem_free(selfIPv6AddrValid);
945 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530946 EXIT();
Gopichand Nakkala746a9452013-06-11 12:45:54 +0530947 return;
948}
949#endif
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530950
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530951void __hdd_ipv4_notifier_work_queue(struct work_struct *work)
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530952{
953 hdd_adapter_t* pAdapter =
954 container_of(work, hdd_adapter_t, ipv4NotifierWorkQueue);
955 hdd_context_t *pHddCtx;
956 int status;
957
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530958 ENTER();
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530959 if (NULL == pAdapter)
960 {
961 hddLog(LOGE, FL("Adapter is invalid"));
962 return;
963 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530964 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
965 status = wlan_hdd_validate_context(pHddCtx);
966 if (0 != status)
967 {
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530968 return;
969 }
970
Deepthi Gowri5933f402014-01-23 17:48:24 +0530971 if ( VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid)
972 {
973 pHddCtx->sus_res_mcastbcast_filter =
974 pHddCtx->configuredMcastBcastFilter;
Sushant Kaushik439d4c72014-05-12 16:39:51 +0530975 hddLog(LOG1, FL("saving configuredMcastBcastFilter = %d"),
976 pHddCtx->sus_res_mcastbcast_filter);
Deepthi Gowri5933f402014-01-23 17:48:24 +0530977 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
978 }
979
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530980 if ((eConnectionState_Associated ==
981 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)
Deepthi Gowri5933f402014-01-23 17:48:24 +0530982 && (pHddCtx->hdd_wlan_suspended))
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530983 {
984 // This invocation being part of the IPv4 registration callback,
985 // we are passing second parameter as 2 to avoid registration
986 // of IPv4 notifier again.
987 hdd_conf_arp_offload(pAdapter, 2);
988 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530989 EXIT();
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +0530990}
991
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530992void hdd_ipv4_notifier_work_queue(struct work_struct *work)
993{
994 vos_ssr_protect(__func__);
995 __hdd_ipv4_notifier_work_queue(work);
996 vos_ssr_unprotect(__func__);
997}
998
Mukul Sharmaa78cf6b2015-02-24 16:59:01 +0530999int __wlan_hdd_ipv4_changed(struct notifier_block *nb,
Vinay Krishna Eranna83b0ef72014-11-19 16:56:20 +05301000 unsigned long data, void *arg)
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301001{
1002 struct in_ifaddr *ifa = (struct in_ifaddr *)arg;
1003 struct in_ifaddr **ifap = NULL;
1004 struct in_device *in_dev;
1005
1006 struct net_device *ndev = ifa->ifa_dev->dev;
Vinay Krishna Eranna55029602015-02-06 15:43:35 +05301007 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05301008 hdd_context_t *pHddCtx;
Vinay Krishna Eranna55029602015-02-06 15:43:35 +05301009 VOS_STATUS vos_status;
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05301010 int status;
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05301011
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05301012 ENTER();
Vinay Krishna Eranna55029602015-02-06 15:43:35 +05301013 pHddCtx = container_of(nb, hdd_context_t, ipv4_notifier);
1014 status = wlan_hdd_validate_context(pHddCtx);
1015 if (0 != status)
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301016 {
Vinay Krishna Eranna55029602015-02-06 15:43:35 +05301017 return NOTIFY_DONE;
1018 }
Vinay Krishna Eranna83b0ef72014-11-19 16:56:20 +05301019
Vinay Krishna Eranna55029602015-02-06 15:43:35 +05301020 vos_status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
1021 while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == vos_status)
1022 {
1023 if (pAdapterNode->pAdapter && pAdapterNode->pAdapter->dev == ndev &&
1024 (pAdapterNode->pAdapter->device_mode == WLAN_HDD_INFRA_STATION ||
1025 pAdapterNode->pAdapter->device_mode == WLAN_HDD_P2P_CLIENT))
1026 {
1027 if ((pHddCtx->cfg_ini->nEnableSuspend !=
Vinay Krishna Eranna83b0ef72014-11-19 16:56:20 +05301028 WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER)
Vinay Krishna Eranna55029602015-02-06 15:43:35 +05301029 || (!pHddCtx->cfg_ini->fhostArpOffload))
1030 {
1031 hddLog(LOG1, FL("Offload not enabled MCBC=%d, ARPOffload=%d"),
1032 pHddCtx->cfg_ini->nEnableSuspend,
1033 pHddCtx->cfg_ini->fhostArpOffload);
1034 return NOTIFY_DONE;
1035 }
Vinay Krishna Eranna83b0ef72014-11-19 16:56:20 +05301036
Vinay Krishna Eranna55029602015-02-06 15:43:35 +05301037 if ((in_dev =
1038 __in_dev_get_rtnl(pAdapterNode->pAdapter->dev)) != NULL)
1039 {
1040 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
1041 ifap = &ifa->ifa_next)
1042 {
1043 if (!strcmp(pAdapterNode->pAdapter->dev->name,
1044 ifa->ifa_label))
1045 {
1046 break; /* found */
1047 }
1048 }
1049 }
1050 if(ifa && ifa->ifa_local)
1051 {
1052 schedule_work(&pAdapterNode->pAdapter->ipv4NotifierWorkQueue);
1053 }
1054 break;
1055 }
1056 vos_status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
1057 pAdapterNode = pNext;
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301058 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05301059 EXIT();
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301060 return NOTIFY_DONE;
1061}
1062
Mukul Sharmaa78cf6b2015-02-24 16:59:01 +05301063int wlan_hdd_ipv4_changed(struct notifier_block *nb,
1064 unsigned long data, void *arg)
1065{
1066 int ret;
1067 vos_ssr_protect(__func__);
1068 ret = __wlan_hdd_ipv4_changed( nb, data, arg);
1069 vos_ssr_unprotect(__func__);
1070 return ret;
1071}
1072
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301073/**----------------------------------------------------------------------------
1074
1075 \brief hdd_conf_arp_offload() - Configure ARP offload
1076
1077 Called during SUSPEND to configure the ARP offload (MC BC filter) which
1078 reduces power consumption.
1079
1080 \param - pAdapter -Adapter context for which ARP offload is to be configured
1081 \param - fenable - 0 - disable.
1082 1 - enable. (with IPv4 notifier registration)
1083 2 - enable. (without IPv4 notifier registration)
1084
1085 \return -
1086 VOS_STATUS_SUCCESS - on successful operation
1087 VOS_STATUS_E_FAILURE - on failure of operation
1088-----------------------------------------------------------------------------*/
1089VOS_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, int fenable)
Jeff Johnson295189b2012-06-20 16:38:30 -07001090{
1091 struct in_ifaddr **ifap = NULL;
1092 struct in_ifaddr *ifa = NULL;
1093 struct in_device *in_dev;
1094 int i = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001095 tSirHostOffloadReq offLoadRequest;
Yathish9f22e662012-12-10 14:21:35 -08001096 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001097
Sushant Kaushik87787972015-09-11 16:05:00 +05301098 hddLog(VOS_TRACE_LEVEL_INFO, FL(" fenable = %d "), fenable);
Jeff Johnson295189b2012-06-20 16:38:30 -07001099
Jeff Johnson295189b2012-06-20 16:38:30 -07001100 if(fenable)
1101 {
1102 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
1103 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301104 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001105 ifap = &ifa->ifa_next)
1106 {
1107 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
1108 {
1109 break; /* found */
1110 }
1111 }
1112 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001113 if(ifa && ifa->ifa_local)
1114 {
1115 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
1116 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
1117
Arif Hussain6d2a3322013-11-17 19:50:10 -08001118 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Enabled", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001119
Amar Singhald53568e2013-09-26 11:03:45 -07001120 if (((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
1121 pHddCtx->sus_res_mcastbcast_filter) ||
1122 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
1123 pHddCtx->sus_res_mcastbcast_filter)) &&
1124 (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid))
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -07001125 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301126 offLoadRequest.enableOrDisable =
Amar Singhald53568e2013-09-26 11:03:45 -07001127 SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
1128 hddLog(VOS_TRACE_LEVEL_INFO,
1129 "offload: inside arp offload conditional check");
Jeff Johnson295189b2012-06-20 16:38:30 -07001130 }
Amar Singhald53568e2013-09-26 11:03:45 -07001131
1132 hddLog(VOS_TRACE_LEVEL_INFO, "offload: arp filter programmed = %d",
1133 offLoadRequest.enableOrDisable);
1134
Jeff Johnson295189b2012-06-20 16:38:30 -07001135 //converting u32 to IPV4 address
1136 for(i = 0 ; i < 4; i++)
1137 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301138 offLoadRequest.params.hostIpv4Addr[i] =
Jeff Johnson295189b2012-06-20 16:38:30 -07001139 (ifa->ifa_local >> (i*8) ) & 0xFF ;
1140 }
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301141 hddLog(VOS_TRACE_LEVEL_INFO, " Enable SME HostOffload: %d.%d.%d.%d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001142 offLoadRequest.params.hostIpv4Addr[0],
1143 offLoadRequest.params.hostIpv4Addr[1],
1144 offLoadRequest.params.hostIpv4Addr[2],
1145 offLoadRequest.params.hostIpv4Addr[3]);
1146
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301147 if (eHAL_STATUS_SUCCESS !=
1148 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1149 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -07001150 {
1151 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to enable HostOffload "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001152 "feature", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001153 return VOS_STATUS_E_FAILURE;
1154 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001155 }
1156 else
1157 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05301158 hddLog(VOS_TRACE_LEVEL_ERROR, FL("IP Address is not assigned"));
1159 return VOS_STATUS_E_AGAIN;
Jeff Johnson295189b2012-06-20 16:38:30 -07001160 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301161
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05301162 return VOS_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07001163 }
1164 else
1165 {
1166 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
1167 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
1168 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
1169
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301170 if (eHAL_STATUS_SUCCESS !=
1171 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1172 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -07001173 {
1174 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to disable host "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001175 "offload feature", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001176 return VOS_STATUS_E_FAILURE;
1177 }
1178 return VOS_STATUS_SUCCESS;
1179 }
1180}
1181
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301182/*
1183 * This function is called before setting mcbc filters
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301184 * to modify filter value considering Different Offloads
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301185*/
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301186void hdd_mcbc_filter_modification(hdd_context_t* pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301187 tANI_U8 *pMcBcFilter)
1188{
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301189 if (NULL == pHddCtx)
1190 {
1191 hddLog(VOS_TRACE_LEVEL_ERROR, FL("NULL HDD context passed"));
1192 return;
1193 }
1194
1195 *pMcBcFilter = pHddCtx->configuredMcastBcastFilter;
1196 if (pHddCtx->cfg_ini->fhostArpOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301197 {
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301198 /* ARP offload is enabled, do not block bcast packets at RXP
1199 * Will be using Bitmasking to reset the filter. As we have
1200 * disable Broadcast filtering, Anding with the negation
1201 * of Broadcast BIT
1202 */
Agarwal Ashishff451a32015-07-28 01:01:29 +05301203 hddLog(VOS_TRACE_LEVEL_INFO, FL(" ARP offload is enabled"));
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301204 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301205 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301206
1207#ifdef WLAN_NS_OFFLOAD
1208 if (pHddCtx->cfg_ini->fhostNSOffload)
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301209 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301210 /* NS offload is enabled, do not block mcast packets at RXP
1211 * Will be using Bitmasking to reset the filter. As we have
1212 * disable Multicast filtering, Anding with the negation
1213 * of Multicast BIT
1214 */
Agarwal Ashishff451a32015-07-28 01:01:29 +05301215 hddLog(VOS_TRACE_LEVEL_INFO, FL(" NS offload is enabled"));
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301216 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301217 }
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301218#endif
1219
Amar Singhald08ce752014-03-21 16:28:27 -07001220 if ((pHddCtx->cfg_ini->fEnableMCAddrList) && WDA_IS_MCAST_FLT_ENABLE_IN_FW)
1221 {
1222 *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST);
1223 }
1224
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301225 pHddCtx->configuredMcastBcastFilter = *pMcBcFilter;
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301226}
1227
Jeff Johnson295189b2012-06-20 16:38:30 -07001228void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter)
1229{
1230 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001231 tpSirWlanSetRxpFilters wlanRxpFilterParam =
1232 vos_mem_malloc(sizeof(tSirWlanSetRxpFilters));
Agarwal Ashishff451a32015-07-28 01:01:29 +05301233 if (NULL == wlanRxpFilterParam)
Jeff Johnson295189b2012-06-20 16:38:30 -07001234 {
1235 hddLog(VOS_TRACE_LEVEL_FATAL,
1236 "%s: vos_mem_alloc failed ", __func__);
1237 return;
1238 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001239 hddLog(VOS_TRACE_LEVEL_INFO,
1240 "%s: Configuring Mcast/Bcast Filter Setting. setfilter %d", __func__, setfilter);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301241 if (TRUE == setfilter)
1242 {
Gopichand Nakkala746a9452013-06-11 12:45:54 +05301243 hdd_mcbc_filter_modification(pHddCtx,
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301244 &wlanRxpFilterParam->configuredMcstBcstFilterSetting);
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301245 }
1246 else
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301247 {
1248 /*Use the current configured value to clear*/
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301249 wlanRxpFilterParam->configuredMcstBcstFilterSetting =
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05301250 pHddCtx->configuredMcastBcastFilter;
1251 }
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +05301252
Jeff Johnson295189b2012-06-20 16:38:30 -07001253 wlanRxpFilterParam->setMcstBcstFilter = setfilter;
Jeff Johnson295189b2012-06-20 16:38:30 -07001254 halStatus = sme_ConfigureRxpFilter(pHddCtx->hHal, wlanRxpFilterParam);
Masti, Narayanraddibdc261d2015-01-22 15:59:49 +05301255
1256 if (setfilter && (eHAL_STATUS_SUCCESS == halStatus))
Agarwal Ashishff451a32015-07-28 01:01:29 +05301257 {
Masti, Narayanraddibdc261d2015-01-22 15:59:49 +05301258 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
Agarwal Ashishff451a32015-07-28 01:01:29 +05301259 }
Masti, Narayanraddibdc261d2015-01-22 15:59:49 +05301260
1261 hddLog(VOS_TRACE_LEVEL_INFO, "%s to post set/reset filter to"
1262 "lower mac with status %d"
1263 "configuredMcstBcstFilterSetting = %d"
1264 "setMcstBcstFilter = %d",(eHAL_STATUS_SUCCESS != halStatus) ?
1265 "Failed" : "Success", halStatus,
1266 wlanRxpFilterParam->configuredMcstBcstFilterSetting,
1267 wlanRxpFilterParam->setMcstBcstFilter);
1268
Chilam Ngc4244af2013-04-01 15:37:32 -07001269 if (eHAL_STATUS_SUCCESS != halStatus)
1270 vos_mem_free(wlanRxpFilterParam);
Jeff Johnson295189b2012-06-20 16:38:30 -07001271}
1272
Jeff Johnson295189b2012-06-20 16:38:30 -07001273static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx,
1274 hdd_adapter_t *pAdapter)
1275{
1276 eHalStatus halStatus = eHAL_STATUS_FAILURE;
1277 tpSirWlanSuspendParam wlanSuspendParam =
1278 vos_mem_malloc(sizeof(tSirWlanSuspendParam));
1279
Amar Singhald53568e2013-09-26 11:03:45 -07001280 if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid) {
1281 pHddCtx->sus_res_mcastbcast_filter =
1282 pHddCtx->configuredMcastBcastFilter;
1283 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
1284 hddLog(VOS_TRACE_LEVEL_INFO, "offload: hdd_conf_suspend_ind");
1285 hddLog(VOS_TRACE_LEVEL_INFO, "configuredMCastBcastFilter saved = %d",
1286 pHddCtx->configuredMcastBcastFilter);
1287
1288 }
1289
Amar Singhal49fdfd52013-08-13 13:25:12 -07001290
Jeff Johnson295189b2012-06-20 16:38:30 -07001291 if(NULL == wlanSuspendParam)
1292 {
1293 hddLog(VOS_TRACE_LEVEL_FATAL,
1294 "%s: vos_mem_alloc failed ", __func__);
1295 return;
1296 }
1297
Amar Singhald53568e2013-09-26 11:03:45 -07001298 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001299 "%s: send wlan suspend indication", __func__);
1300
1301 if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER))
1302 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301303 //Configure supported OffLoads
1304 hdd_conf_hostoffload(pAdapter, TRUE);
1305 wlanSuspendParam->configuredMcstBcstFilterSetting = pHddCtx->configuredMcastBcastFilter;
Sushant Kaushik439d4c72014-05-12 16:39:51 +05301306 hddLog(VOS_TRACE_LEVEL_INFO,
1307 FL("saving configuredMcastBcastFilterSetting = %d"),
1308 wlanSuspendParam->configuredMcstBcstFilterSetting);
Jeff Johnson295189b2012-06-20 16:38:30 -07001309#ifdef WLAN_FEATURE_PACKET_FILTERING
madan mohan koyyalamudibfd9cef2013-07-01 18:39:37 +05301310 /* During suspend, configure MC Addr list filter to the firmware
1311 * function takes care of checking necessary conditions before
1312 * configuring.
1313 */
1314 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001315#endif
Amar Singhald08ce752014-03-21 16:28:27 -07001316
1317 if( (pHddCtx->cfg_ini->fEnableMCAddrList) && WDA_IS_MCAST_FLT_ENABLE_IN_FW)
1318 {
1319
1320 hddLog(VOS_TRACE_LEVEL_INFO, "offload: MCaddrlist: FW capability set ");
1321 pHddCtx->configuredMcastBcastFilter &=
1322 ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST);
1323 }
1324
1325 wlanSuspendParam->configuredMcstBcstFilterSetting =
1326 pHddCtx->configuredMcastBcastFilter;
Jeff Johnson295189b2012-06-20 16:38:30 -07001327 }
1328
1329 halStatus = sme_ConfigureSuspendInd(pHddCtx->hHal, wlanSuspendParam);
1330 if(eHAL_STATUS_SUCCESS == halStatus)
1331 {
1332 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
Chilam Ngc4244af2013-04-01 15:37:32 -07001333 } else {
c_hpothuffdb5272013-10-02 16:42:35 +05301334 hddLog(VOS_TRACE_LEVEL_ERROR,
1335 FL("sme_ConfigureSuspendInd returned failure %d"), halStatus);
Chilam Ngc4244af2013-04-01 15:37:32 -07001336 vos_mem_free(wlanSuspendParam);
Jeff Johnson295189b2012-06-20 16:38:30 -07001337 }
1338}
1339
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301340static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001341{
Chilam Ngc4244af2013-04-01 15:37:32 -07001342 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Yathish9f22e662012-12-10 14:21:35 -08001343 hdd_context_t* pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Chilam Ngc4244af2013-04-01 15:37:32 -07001344 tpSirWlanResumeParam wlanResumeParam;
Jeff Johnson295189b2012-06-20 16:38:30 -07001345
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301346 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001347 "%s: send wlan resume indication", __func__);
1348
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301349 wlanResumeParam = vos_mem_malloc(sizeof(tSirWlanResumeParam));
1350
1351 if (NULL == wlanResumeParam)
Jeff Johnson295189b2012-06-20 16:38:30 -07001352 {
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301353 hddLog(VOS_TRACE_LEVEL_FATAL,
1354 "%s: memory allocation failed for wlanResumeParam ", __func__);
1355 return;
Jeff Johnson295189b2012-06-20 16:38:30 -07001356 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001357
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301358 //Disable supported OffLoads
1359 hdd_conf_hostoffload(pAdapter, FALSE);
1360
1361 wlanResumeParam->configuredMcstBcstFilterSetting =
1362 pHddCtx->configuredMcastBcastFilter;
1363 halStatus = sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam);
1364 if (eHAL_STATUS_SUCCESS != halStatus)
1365 {
c_hpothuffdb5272013-10-02 16:42:35 +05301366 hddLog(VOS_TRACE_LEVEL_ERROR,
1367 "%s: sme_ConfigureResumeReq return failure %d", __func__, halStatus);
Madan Mohan Koyyalamudia6d7eab2013-09-25 10:21:22 +05301368 vos_mem_free(wlanResumeParam);
1369 }
1370
1371 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
1372
Amar Singhalf8ba2b82013-12-02 12:54:38 -08001373 if (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid) {
1374 pHddCtx->configuredMcastBcastFilter =
1375 pHddCtx->sus_res_mcastbcast_filter;
1376 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_FALSE;
1377 }
Amar Singhald53568e2013-09-26 11:03:45 -07001378
1379 hddLog(VOS_TRACE_LEVEL_INFO,
1380 "offload: in hdd_conf_resume_ind, restoring configuredMcastBcastFilter");
1381 hddLog(VOS_TRACE_LEVEL_INFO, "configuredMcastBcastFilter = %d",
1382 pHddCtx->configuredMcastBcastFilter);
Amar Singhal49fdfd52013-08-13 13:25:12 -07001383
Chilam Ngc4244af2013-04-01 15:37:32 -07001384
madan mohan koyyalamudibfd9cef2013-07-01 18:39:37 +05301385#ifdef WLAN_FEATURE_PACKET_FILTERING
1386 /* Filer was applied during suspend inditication
1387 * clear it when we resume.
1388 */
1389 wlan_hdd_set_mc_addr_list(pAdapter, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001390#endif
1391}
Jeff Johnson295189b2012-06-20 16:38:30 -07001392
Jeff Johnson295189b2012-06-20 16:38:30 -07001393//Suspend routine registered with Android OS
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001394void hdd_suspend_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001395{
1396 hdd_context_t *pHddCtx = NULL;
1397 v_CONTEXT_t pVosContext = NULL;
1398
Jeff Johnson295189b2012-06-20 16:38:30 -07001399 VOS_STATUS status;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301400 hdd_adapter_t *pAdapter = NULL;
1401 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301402 bool hdd_enter_bmps = FALSE;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001403
Jeff Johnson295189b2012-06-20 16:38:30 -07001404 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__);
1405
1406 //Get the global VOSS context.
1407 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1408 if(!pVosContext) {
1409 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1410 return;
1411 }
1412
1413 //Get the HDD context.
1414 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1415
1416 if(!pHddCtx) {
1417 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1418 return;
1419 }
1420
1421 if (pHddCtx->isLogpInProgress) {
1422 hddLog(VOS_TRACE_LEVEL_ERROR,
1423 "%s: Ignore suspend wlan, LOGP in progress!", __func__);
1424 return;
1425 }
1426
Padma, Santhosh Kumar2ee1ad02015-01-12 16:05:47 +05301427 if (pHddCtx->hdd_wlan_suspended)
1428 {
1429 hddLog(VOS_TRACE_LEVEL_ERROR,
1430 "%s: Ignore suspend wlan, Already suspended!", __func__);
1431 return;
1432 }
1433
Mahesh A Saptasagar0ea15c22014-10-28 15:26:57 +05301434 pHddCtx->hdd_wlan_suspended = TRUE;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301435 hdd_set_pwrparams(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001436 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1437 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1438 {
1439 pAdapter = pAdapterNode->pAdapter;
1440 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001441 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001442 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
1443
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001444 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001445 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1446 pAdapterNode = pNext;
1447 continue;
1448 }
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301449 /* Avoid multiple enter/exit BMPS in this while loop using
1450 * hdd_enter_bmps flag
1451 */
1452 if (FALSE == hdd_enter_bmps && (BMPS == pmcGetPmcState(pHddCtx->hHal)))
1453 {
1454 hdd_enter_bmps = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001455
madan mohan koyyalamudi459d6e72013-07-09 23:36:00 +05301456 /* If device was already in BMPS, and dynamic DTIM is set,
1457 * exit(set the device to full power) and enter BMPS again
1458 * to reflect new DTIM value */
1459 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
1460
1461 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
1462
1463 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1464 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001465#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1466 if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1467 {
1468 //stop the interface before putting the chip to standby
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05301469 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001470 netif_tx_disable(pAdapter->dev);
1471 netif_carrier_off(pAdapter->dev);
1472 }
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301473 else if (pHddCtx->cfg_ini->nEnableSuspend ==
Jeff Johnson295189b2012-06-20 16:38:30 -07001474 WLAN_MAP_SUSPEND_TO_DEEP_SLEEP)
1475 {
1476 //Execute deep sleep procedure
1477 hdd_enter_deep_sleep(pHddCtx, pAdapter);
1478 }
1479#endif
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301480
1481 /*Suspend notification sent down to driver*/
1482 hdd_conf_suspend_ind(pHddCtx, pAdapter);
1483
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05301484 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1485 pAdapterNode = pNext;
1486 }
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301487
Jeff Johnson295189b2012-06-20 16:38:30 -07001488#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1489 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1490 {
1491 hdd_enter_standby(pHddCtx);
1492 }
1493#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001494
1495 return;
1496}
1497
1498static void hdd_PowerStateChangedCB
1499(
1500 v_PVOID_t callbackContext,
1501 tPmcState newState
1502)
1503{
1504 hdd_context_t *pHddCtx = callbackContext;
Mukul Sharmabb94ece2014-04-04 21:22:15 +05301505
Jeff Johnson295189b2012-06-20 16:38:30 -07001506 /* if the driver was not in BMPS during early suspend,
1507 * the dynamic DTIM is now updated at Riva */
1508 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended
1509 && pHddCtx->cfg_ini->enableDynamicDTIM
1510 && (pHddCtx->hdd_ignore_dtim_enabled == FALSE))
1511 {
1512 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1513 }
1514 spin_lock(&pHddCtx->filter_lock);
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301515 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended)
1516 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001517 spin_unlock(&pHddCtx->filter_lock);
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301518 if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid)
1519 {
Amar Singhald53568e2013-09-26 11:03:45 -07001520 pHddCtx->sus_res_mcastbcast_filter =
1521 pHddCtx->configuredMcastBcastFilter;
1522 pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE;
1523
1524 hddLog(VOS_TRACE_LEVEL_INFO, "offload: callback to associated");
1525 hddLog(VOS_TRACE_LEVEL_INFO, "saving configuredMcastBcastFilter = %d",
1526 pHddCtx->configuredMcastBcastFilter);
1527 hddLog(VOS_TRACE_LEVEL_INFO,
1528 "offload: calling hdd_conf_mcastbcast_filter");
1529
1530 }
1531
Jeff Johnson295189b2012-06-20 16:38:30 -07001532 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001533 if(pHddCtx->hdd_mcastbcast_filter_set != TRUE)
1534 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__);
Mukul Sharmabb94ece2014-04-04 21:22:15 +05301535 }
Amar Singhal49fdfd52013-08-13 13:25:12 -07001536 else
Mihir Shete793209f2014-01-06 11:01:12 +05301537 {
1538 /* Android framework can send resume request when the WCN chip is
1539 * in IMPS mode. When the chip exits IMPS mode the firmware will
1540 * restore all the registers to the state they were before the chip
1541 * entered IMPS and so our hardware filter settings confgured by the
1542 * resume request will be lost. So reconfigure the filters on detecting
1543 * a change in the power state of the WCN chip.
1544 */
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301545 spin_unlock(&pHddCtx->filter_lock);
Mihir Shete793209f2014-01-06 11:01:12 +05301546 if (IMPS != newState)
1547 {
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301548 spin_lock(&pHddCtx->filter_lock);
Mihir Shete793209f2014-01-06 11:01:12 +05301549 if (FALSE == pHddCtx->hdd_wlan_suspended)
1550 {
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301551 spin_unlock(&pHddCtx->filter_lock);
Mihir Shete793209f2014-01-06 11:01:12 +05301552 hddLog(VOS_TRACE_LEVEL_INFO,
1553 "Not in IMPS/BMPS and suspended state");
1554 hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
1555 }
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301556 else
1557 {
1558 spin_unlock(&pHddCtx->filter_lock);
1559 }
Mihir Shete793209f2014-01-06 11:01:12 +05301560 }
Agarwal Ashish469b1e52014-01-17 09:13:10 +05301561 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001562}
1563
Jeff Johnson295189b2012-06-20 16:38:30 -07001564void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx)
1565{
1566 v_CONTEXT_t pVosContext;
1567 tHalHandle smeContext;
1568
1569 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1570 if (NULL == pVosContext)
1571 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001572 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001573 return;
1574 }
1575 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1576 if (NULL == smeContext)
1577 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001578 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001579 return;
1580 }
1581
1582 spin_lock_init(&pHddCtx->filter_lock);
1583 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1584 pHddCtx->cfg_ini->nEnableSuspend)
1585 {
1586 pmcRegisterDeviceStateUpdateInd(smeContext,
1587 hdd_PowerStateChangedCB, pHddCtx);
1588 }
1589}
1590
1591void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx)
1592{
1593 v_CONTEXT_t pVosContext;
1594 tHalHandle smeContext;
1595
1596 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1597 if (NULL == pVosContext)
1598 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001599 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001600 return;
1601 }
1602 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1603 if (NULL == smeContext)
1604 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001605 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001606 return;
1607 }
1608
1609 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1610 pHddCtx->cfg_ini->nEnableSuspend)
1611 {
1612 pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB);
1613 }
1614}
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301615
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301616#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301617void hdd_conf_gtk_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301618{
1619 eHalStatus ret;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301620 tSirGtkOffloadParams hddGtkOffloadReqParams;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301621 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1622
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301623 if(fenable)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301624 {
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301625 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1626 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags ))
1627 {
1628 vos_mem_copy(&hddGtkOffloadReqParams,
1629 &pHddStaCtx->gtkOffloadReqParams,
1630 sizeof (tSirGtkOffloadParams));
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301631
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301632 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
1633 &hddGtkOffloadReqParams, pAdapter->sessionId);
1634 if (eHAL_STATUS_SUCCESS != ret)
1635 {
1636 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1637 "%s: sme_SetGTKOffload failed, returned %d",
1638 __func__, ret);
1639 return;
1640 }
1641
1642 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1643 "%s: sme_SetGTKOffload successfull", __func__);
1644 }
1645
1646 }
1647 else
1648 {
1649 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1650 (0 == memcmp(&pHddStaCtx->gtkOffloadReqParams.bssId,
1651 &pHddStaCtx->conn_info.bssId, WNI_CFG_BSSID_LEN)) &&
1652 (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags))
1653 {
1654
1655 /* Host driver has previously offloaded GTK rekey */
1656 ret = sme_GetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301657 wlan_hdd_cfg80211_update_replayCounterCallback,
1658 pAdapter, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301659 if (eHAL_STATUS_SUCCESS != ret)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301660
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301661 {
1662 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1663 "%s: sme_GetGTKOffload failed, returned %d",
1664 __func__, ret);
1665 return;
1666 }
1667 else
1668 {
1669 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1670 "%s: sme_GetGTKOffload successful",
1671 __func__);
1672
1673 /* Sending GTK offload dissable */
1674 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
1675 sizeof (tSirGtkOffloadParams));
1676 hddGtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE;
1677 ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05301678 &hddGtkOffloadReqParams, pAdapter->sessionId);
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301679 if (eHAL_STATUS_SUCCESS != ret)
1680 {
1681 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1682 "%s: failed to dissable GTK offload, returned %d",
1683 __func__, ret);
1684 return;
1685 }
1686 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1687 "%s: successfully dissabled GTK offload request to HAL",
1688 __func__);
1689 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301690 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301691 }
Gopichand Nakkalab03e8082013-05-30 18:09:25 +05301692 return;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301693}
1694#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
Jeff Johnson295189b2012-06-20 16:38:30 -07001695
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001696void hdd_resume_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001697{
1698 hdd_context_t *pHddCtx = NULL;
1699 hdd_adapter_t *pAdapter = NULL;
1700 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1701 VOS_STATUS status;
1702 v_CONTEXT_t pVosContext = NULL;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08001703
Jeff Johnson295189b2012-06-20 16:38:30 -07001704 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
1705
1706 //Get the global VOSS context.
1707 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1708 if(!pVosContext) {
1709 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1710 return;
1711 }
1712
1713 //Get the HDD context.
1714 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1715
1716 if(!pHddCtx) {
1717 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1718 return;
1719 }
1720
Agarwal Ashish971c2882013-10-30 20:11:12 +05301721 if (pHddCtx->isLogpInProgress)
1722 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001723 hddLog(VOS_TRACE_LEVEL_INFO,
1724 "%s: Ignore resume wlan, LOGP in progress!", __func__);
1725 return;
1726 }
1727
Padma, Santhosh Kumar2ee1ad02015-01-12 16:05:47 +05301728 if (!pHddCtx->hdd_wlan_suspended)
1729 {
Ratheesh S P36dbc932015-08-07 14:28:57 +05301730 hddLog(VOS_TRACE_LEVEL_INFO,
Padma, Santhosh Kumar2ee1ad02015-01-12 16:05:47 +05301731 "%s: Ignore resume wlan, Already resumed!", __func__);
1732 return;
1733 }
1734
Jeff Johnson295189b2012-06-20 16:38:30 -07001735 pHddCtx->hdd_wlan_suspended = FALSE;
1736 /*loop through all adapters. Concurrency */
1737 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1738
1739 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1740 {
1741 pAdapter = pAdapterNode->pAdapter;
1742 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001743 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001744 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001745 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001746 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1747 pAdapterNode = pNext;
1748 continue;
1749 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301750
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05301751
Jeff Johnson295189b2012-06-20 16:38:30 -07001752#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1753 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP)
1754 {
1755 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__);
1756 hdd_exit_deep_sleep(pAdapter);
1757 }
1758#endif
1759
1760 if(pHddCtx->hdd_ignore_dtim_enabled == TRUE)
1761 {
1762 /*Switch back to DTIM 1*/
1763 tSirSetPowerParamsReq powerRequest = { 0 };
1764
1765 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
1766 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07001767 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001768
1769 /*Disabled ModulatedDTIM if enabled on suspend*/
1770 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1771 powerRequest.uDTIMPeriod = 0;
1772
1773 /* Update ignoreDTIM and ListedInterval in CFG with default values */
1774 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1775 NULL, eANI_BOOLEAN_FALSE);
1776 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1777 NULL, eANI_BOOLEAN_FALSE);
1778
1779 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001780 "Switch to DTIM%d",powerRequest.uListenInterval);
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08001781 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001782
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301783 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
1784 {
1785 /* put the device into full power */
1786 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001787
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301788 /* put the device back into BMPS */
1789 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
Jeff Johnson295189b2012-06-20 16:38:30 -07001790
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301791 pHddCtx->hdd_ignore_dtim_enabled = FALSE;
1792 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001793 }
1794
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301795 hdd_conf_resume_ind(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001796 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1797 pAdapterNode = pNext;
1798 }
1799
1800#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1801 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY)
1802 {
1803 hdd_exit_standby(pHddCtx);
1804 }
1805#endif
1806
Jeff Johnson295189b2012-06-20 16:38:30 -07001807 return;
1808}
1809
Jeff Johnson295189b2012-06-20 16:38:30 -07001810VOS_STATUS hdd_wlan_reset_initialization(void)
1811{
Jeff Johnson295189b2012-06-20 16:38:30 -07001812 v_CONTEXT_t pVosContext = NULL;
1813
1814 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1815
1816 //Get the global VOSS context.
1817 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1818 if(!pVosContext)
1819 {
1820 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1821 return VOS_STATUS_E_FAILURE;
1822 }
1823
1824 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__);
1825
1826 // Prevent the phone from going to sleep
Sushant Kaushik83392fa2015-05-05 17:44:40 +05301827 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT);
Jeff Johnson295189b2012-06-20 16:38:30 -07001828
Jeff Johnson295189b2012-06-20 16:38:30 -07001829 return VOS_STATUS_SUCCESS;
1830}
1831
1832
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001833/*
1834 * Based on the ioctl command recieved by HDD, put WLAN driver
1835 * into the quiet mode. This is the same as the early suspend
1836 * notification that driver used to listen
1837 */
1838void hdd_set_wlan_suspend_mode(bool suspend)
Jeff Johnson295189b2012-06-20 16:38:30 -07001839{
Sandeep Puligilla308288f2014-06-05 22:21:46 +05301840 vos_ssr_protect(__func__);
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001841 if (suspend)
1842 hdd_suspend_wlan();
1843 else
1844 hdd_resume_wlan();
Sandeep Puligilla308288f2014-06-05 22:21:46 +05301845 vos_ssr_unprotect(__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001846}
1847
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001848static void hdd_ssr_timer_init(void)
1849{
1850 init_timer(&ssr_timer);
1851}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001852
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001853static void hdd_ssr_timer_del(void)
1854{
1855 del_timer(&ssr_timer);
1856 ssr_timer_started = false;
1857}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001858
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001859static void hdd_ssr_timer_cb(unsigned long data)
1860{
1861 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD SSR timer expired", __func__);
Sameer Thalappile5637f42013-08-07 15:46:55 -07001862
1863#ifdef WCN_PRONTO
1864 if (wcnss_hardware_type() == WCNSS_PRONTO_HW)
1865 wcnss_pronto_log_debug_regs();
1866#endif
1867
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001868 VOS_BUG(0);
1869}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001870
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001871static void hdd_ssr_timer_start(int msec)
1872{
1873 if(ssr_timer_started)
1874 {
1875 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: trying to start SSR timer when it's running"
1876 ,__func__);
1877 }
1878 ssr_timer.expires = jiffies + msecs_to_jiffies(msec);
1879 ssr_timer.function = hdd_ssr_timer_cb;
1880 add_timer(&ssr_timer);
1881 ssr_timer_started = true;
1882}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001883
Jeff Johnson295189b2012-06-20 16:38:30 -07001884/* the HDD interface to WLAN driver shutdown,
1885 * the primary shutdown function in SSR
1886 */
1887VOS_STATUS hdd_wlan_shutdown(void)
1888{
1889 VOS_STATUS vosStatus;
1890 v_CONTEXT_t pVosContext = NULL;
1891 hdd_context_t *pHddCtx = NULL;
1892 pVosSchedContext vosSchedContext = NULL;
1893
1894 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__);
1895
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001896 /* if re-init never happens, then do SSR1 */
1897 hdd_ssr_timer_init();
1898 hdd_ssr_timer_start(HDD_SSR_BRING_UP_TIME);
1899
Jeff Johnson295189b2012-06-20 16:38:30 -07001900 /* Get the global VOSS context. */
1901 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1902 if(!pVosContext) {
1903 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1904 return VOS_STATUS_E_FAILURE;
1905 }
1906 /* Get the HDD context. */
1907 pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1908 if(!pHddCtx) {
1909 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1910 return VOS_STATUS_E_FAILURE;
1911 }
c_hpothud662a352013-12-26 15:09:12 +05301912
1913 //Stop the traffic monitor timer
1914 if ( VOS_TIMER_STATE_RUNNING ==
1915 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
1916 {
1917 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
1918 }
1919
Jeff Johnson295189b2012-06-20 16:38:30 -07001920 hdd_reset_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001921 /* DeRegister with platform driver as client for Suspend/Resume */
1922 vosStatus = hddDeregisterPmOps(pHddCtx);
1923 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1924 {
1925 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
1926 }
1927
1928 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
1929 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1930 {
1931 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
1932 }
1933
1934 /* Disable IMPS/BMPS as we do not want the device to enter any power
1935 * save mode on its own during reset sequence
1936 */
1937 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1938 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1939 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1940
1941 vosSchedContext = get_vos_sched_ctxt();
1942
1943 /* Wakeup all driver threads */
1944 if(TRUE == pHddCtx->isMcThreadSuspended){
1945 complete(&vosSchedContext->ResumeMcEvent);
1946 pHddCtx->isMcThreadSuspended= FALSE;
1947 }
1948 if(TRUE == pHddCtx->isTxThreadSuspended){
1949 complete(&vosSchedContext->ResumeTxEvent);
1950 pHddCtx->isTxThreadSuspended= FALSE;
1951 }
1952 if(TRUE == pHddCtx->isRxThreadSuspended){
1953 complete(&vosSchedContext->ResumeRxEvent);
1954 pHddCtx->isRxThreadSuspended= FALSE;
1955 }
1956 /* Reset the Suspend Variable */
1957 pHddCtx->isWlanSuspended = FALSE;
1958
1959 /* Stop all the threads; we do not want any messages to be a processed,
1960 * any more and the best way to ensure that is to terminate the threads
1961 * gracefully.
1962 */
1963 /* Wait for MC to exit */
1964 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
1965 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
1966 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
1967 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
Mihir Sheteb5425f72013-12-19 09:06:13 +05301968 wait_for_completion(&vosSchedContext->McShutdown);
Jeff Johnson295189b2012-06-20 16:38:30 -07001969
1970 /* Wait for TX to exit */
1971 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
1972 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
1973 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
1974 wake_up_interruptible(&vosSchedContext->txWaitQueue);
Mihir Sheteb5425f72013-12-19 09:06:13 +05301975 wait_for_completion(&vosSchedContext->TxShutdown);
Jeff Johnson295189b2012-06-20 16:38:30 -07001976
1977 /* Wait for RX to exit */
1978 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
1979 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
1980 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
1981 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
c_hpothuffdb5272013-10-02 16:42:35 +05301982
Mihir Sheteb5425f72013-12-19 09:06:13 +05301983 wait_for_completion(&vosSchedContext->RxShutdown);
Jeff Johnson295189b2012-06-20 16:38:30 -07001984
1985#ifdef WLAN_BTAMP_FEATURE
1986 vosStatus = WLANBAP_Stop(pVosContext);
1987 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1988 {
1989 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1990 "%s: Failed to stop BAP",__func__);
1991 }
1992#endif //WLAN_BTAMP_FEATURE
1993 vosStatus = vos_wda_shutdown(pVosContext);
c_hpothuffdb5272013-10-02 16:42:35 +05301994 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1995 {
1996 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1997 "%s: Failed to stop wda %d", __func__, vosStatus);
1998 VOS_ASSERT(0);
1999 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002000
2001 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
2002 /* Stop SME - Cannot invoke vos_stop as vos_stop relies
2003 * on threads being running to process the SYS Stop
2004 */
Kiet Lama72a2322013-11-15 11:18:11 +05302005 vosStatus = sme_Stop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
c_hpothuffdb5272013-10-02 16:42:35 +05302006 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2007 {
2008 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2009 "%s: Failed to stop sme %d", __func__, vosStatus);
2010 VOS_ASSERT(0);
2011 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002012
2013 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
2014 /* Stop MAC (PE and HAL) */
2015 vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
c_hpothuffdb5272013-10-02 16:42:35 +05302016 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2017 {
2018 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2019 "%s: Failed to stop mac %d", __func__, vosStatus);
2020 VOS_ASSERT(0);
2021 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002022
2023 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
2024 /* Stop TL */
2025 vosStatus = WLANTL_Stop(pVosContext);
c_hpothuffdb5272013-10-02 16:42:35 +05302026 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2027 {
2028 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2029 "%s: Failed to stop TL %d", __func__, vosStatus);
2030 VOS_ASSERT(0);
2031 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002032
Jeff Johnson295189b2012-06-20 16:38:30 -07002033 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002034 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__);
2035 /* Clean up message queues of TX and MC thread */
2036 vos_sched_flush_mc_mqs(vosSchedContext);
2037 vos_sched_flush_tx_mqs(vosSchedContext);
2038 vos_sched_flush_rx_mqs(vosSchedContext);
Siddharth Bhal7bd19932015-03-03 16:54:36 +05302039#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
2040 wlan_logging_flush_pkt_queue();
2041#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002042
2043 /* Deinit all the TX and MC queues */
2044 vos_sched_deinit_mqs(vosSchedContext);
2045 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__);
2046
2047 /* shutdown VOSS */
2048 vos_shutdown(pVosContext);
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05302049
2050 /*mac context has already been released in mac_close call
2051 so setting it to NULL in hdd context*/
2052 pHddCtx->hHal = (tHalHandle)NULL;
2053
Jeff Johnson295189b2012-06-20 16:38:30 -07002054 if (free_riva_power_on_lock("wlan"))
2055 {
2056 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
2057 __func__);
2058 }
2059 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete"
2060 ,__func__);
2061 return VOS_STATUS_SUCCESS;
2062}
2063
2064
2065
2066/* the HDD interface to WLAN driver re-init.
2067 * This is called to initialize/start WLAN driver after a shutdown.
2068 */
2069VOS_STATUS hdd_wlan_re_init(void)
2070{
2071 VOS_STATUS vosStatus;
2072 v_CONTEXT_t pVosContext = NULL;
2073 hdd_context_t *pHddCtx = NULL;
2074 eHalStatus halStatus;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07002075#ifdef HAVE_WCNSS_CAL_DOWNLOAD
2076 int max_retries = 0;
2077#endif
Siddharth Bhalc7e79b62014-10-10 22:37:38 +05302078#ifdef HAVE_CBC_DONE
2079 int max_cbc_retries = 0;
2080#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002081#ifdef WLAN_BTAMP_FEATURE
2082 hdd_config_t *pConfig = NULL;
2083 WLANBAP_ConfigType btAmpConfig;
2084#endif
2085
Katya Nigam82a93062014-06-04 15:15:36 +05302086 struct device *dev = NULL;
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07002087 hdd_ssr_timer_del();
Sushant Kaushik83392fa2015-05-05 17:44:40 +05302088 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT);
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08002089
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07002090#ifdef HAVE_WCNSS_CAL_DOWNLOAD
2091 /* wait until WCNSS driver downloads NV */
Yue Ma120f9ff2014-02-26 14:53:31 -08002092 while (!wcnss_device_ready() && 10 >= ++max_retries) {
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07002093 msleep(1000);
2094 }
Yue Ma120f9ff2014-02-26 14:53:31 -08002095 if (max_retries >= 10) {
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07002096 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
2097 goto err_re_init;
2098 }
2099#endif
2100
Siddharth Bhalc7e79b62014-10-10 22:37:38 +05302101#ifdef HAVE_CBC_DONE
2102 while (!wcnss_cbc_complete() && 20 >= ++max_cbc_retries) {
2103 msleep(1000);
2104 }
2105 if (max_cbc_retries >= 20) {
2106 hddLog(VOS_TRACE_LEVEL_FATAL, "%s:CBC not completed", __func__);
2107 }
2108#endif
2109
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07002110 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, TRUE);
2111
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08002112 /* The driver should always be initialized in STA mode after SSR */
2113 hdd_set_conparam(0);
2114
Katya Nigam82a93062014-06-04 15:15:36 +05302115 dev = wcnss_wlan_get_device();
2116 if (NULL == dev)
2117 {
2118 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wcnss dev is NULL",__func__);
2119 goto err_re_init;
2120 }
2121
Jeff Johnson295189b2012-06-20 16:38:30 -07002122 /* Re-open VOSS, it is a re-open b'se control transport was never closed. */
Katya Nigam82a93062014-06-04 15:15:36 +05302123 vosStatus = vos_open(&pVosContext, dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07002124 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2125 {
2126 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
2127 goto err_re_init;
2128 }
2129
2130 /* Get the HDD context. */
2131 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
2132 if(!pHddCtx)
2133 {
2134 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
2135 goto err_vosclose;
2136 }
2137
2138 /* Save the hal context in Adapter */
2139 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
2140 if ( NULL == pHddCtx->hHal )
2141 {
2142 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
2143 goto err_vosclose;
2144 }
2145
2146 /* Set the SME configuration parameters. */
2147 vosStatus = hdd_set_sme_config(pHddCtx);
2148 if ( VOS_STATUS_SUCCESS != vosStatus )
2149 {
2150 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
2151 goto err_vosclose;
2152 }
2153
Jeff Johnson295189b2012-06-20 16:38:30 -07002154 vosStatus = vos_preStart( pHddCtx->pvosContext );
2155 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2156 {
2157 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
2158 goto err_vosclose;
2159 }
2160
2161 /* In the integrated architecture we update the configuration from
2162 the INI file and from NV before vOSS has been started so that
2163 the final contents are available to send down to the cCPU */
2164 /* Apply the cfg.ini to cfg.dat */
2165 if (FALSE == hdd_update_config_dat(pHddCtx))
2166 {
2167 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
2168 goto err_vosclose;
2169 }
2170
2171 /* Set the MAC Address, currently this is used by HAL to add self sta.
2172 * Remove this once self sta is added as part of session open. */
2173 halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID,
2174 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
2175 sizeof(pHddCtx->cfg_ini->intfMacAddr[0]));
2176 if (!HAL_STATUS_SUCCESS(halStatus))
2177 {
2178 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
2179 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus);
2180 goto err_vosclose;
2181 }
2182
2183 /* Start VOSS which starts up the SME/MAC/HAL modules and everything else
2184 Note: Firmware image will be read and downloaded inside vos_start API */
2185 vosStatus = vos_start( pVosContext );
2186 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2187 {
2188 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
2189 goto err_vosclose;
2190 }
2191
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07002192 /* Exchange capability info between Host and FW and also get versioning info from FW */
2193 hdd_exchange_version_and_caps(pHddCtx);
2194
Jeff Johnson295189b2012-06-20 16:38:30 -07002195 vosStatus = hdd_post_voss_start_config( pHddCtx );
2196 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2197 {
2198 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
2199 __func__);
2200 goto err_vosstop;
2201 }
2202
Mihir Shete04206452014-11-20 17:50:58 +05302203#ifdef CONFIG_ENABLE_LINUX_REG
Agarwal Ashish6db9d532014-09-30 18:19:10 +05302204 vosStatus = wlan_hdd_init_channels_for_cc(pHddCtx, REINIT);
2205 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2206 {
2207 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels_for_cc failed",
2208 __func__);
2209 goto err_vosstop;
2210 }
Mihir Shete04206452014-11-20 17:50:58 +05302211#endif
Agarwal Ashish6db9d532014-09-30 18:19:10 +05302212
Jeff Johnson295189b2012-06-20 16:38:30 -07002213#ifdef WLAN_BTAMP_FEATURE
2214 vosStatus = WLANBAP_Open(pVosContext);
2215 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
2216 {
2217 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2218 "%s: Failed to open BAP",__func__);
2219 goto err_vosstop;
2220 }
2221 vosStatus = BSL_Init(pVosContext);
2222 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
2223 {
2224 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2225 "%s: Failed to Init BSL",__func__);
2226 goto err_bap_close;
2227 }
2228 vosStatus = WLANBAP_Start(pVosContext);
2229 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2230 {
2231 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2232 "%s: Failed to start TL",__func__);
2233 goto err_bap_close;
2234 }
2235 pConfig = pHddCtx->cfg_ini;
2236 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
2237 vosStatus = WLANBAP_SetConfig(&btAmpConfig);
2238#endif //WLAN_BTAMP_FEATURE
2239
2240 /* Restart all adapters */
2241 hdd_start_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002242 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Anand N Sunkad0cbc27a2014-09-18 12:58:18 +05302243 pHddCtx->btCoexModeSet = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002244 hdd_register_mcast_bcast_filter(pHddCtx);
Agarwal Ashish4b87f922014-06-18 03:03:21 +05302245 wlan_hdd_tdls_init(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002246 /* Register with platform driver as client for Suspend/Resume */
2247 vosStatus = hddRegisterPmOps(pHddCtx);
2248 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2249 {
2250 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
2251 goto err_bap_stop;
2252 }
Hanumantha Reddy Pothulab7dd9972015-07-01 12:24:57 +05302253
2254#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
2255 if (pHddCtx->cfg_ini->wlanLoggingEnable &&
2256 (pHddCtx->cfg_ini->enableFWLogging ||
2257 pHddCtx->cfg_ini->enableMgmtLogging ||
2258 pHddCtx->cfg_ini->enableContFWLogging))
2259 {
2260 hdd_init_frame_logging(pHddCtx);
2261 }
2262#endif
2263
Jeff Johnson295189b2012-06-20 16:38:30 -07002264 /* Allow the phone to go to sleep */
Sushant Kaushik83392fa2015-05-05 17:44:40 +05302265 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT);
Jeff Johnson295189b2012-06-20 16:38:30 -07002266 /* register for riva power on lock */
2267 if (req_riva_power_on_lock("wlan"))
2268 {
2269 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
2270 __func__);
2271 goto err_unregister_pmops;
2272 }
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07002273 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Dasari Srinivas421bde82014-06-25 12:01:44 +05302274#ifdef WLAN_FEATURE_EXTSCAN
2275 sme_EXTScanRegisterCallback(pHddCtx->hHal,
2276 wlan_hdd_cfg80211_extscan_callback,
2277 pHddCtx);
2278#endif /* WLAN_FEATURE_EXTSCAN */
Jeff Johnson295189b2012-06-20 16:38:30 -07002279 goto success;
2280
2281err_unregister_pmops:
2282 hddDeregisterPmOps(pHddCtx);
2283
2284err_bap_stop:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002285#ifdef CONFIG_HAS_EARLYSUSPEND
2286 hdd_unregister_mcast_bcast_filter(pHddCtx);
2287#endif
2288 hdd_close_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002289#ifdef WLAN_BTAMP_FEATURE
Jeff Johnson32d95a32012-09-10 13:15:23 -07002290 WLANBAP_Stop(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07002291#endif
2292
2293#ifdef WLAN_BTAMP_FEATURE
2294err_bap_close:
2295 WLANBAP_Close(pVosContext);
2296#endif
2297
2298err_vosstop:
2299 vos_stop(pVosContext);
2300
2301err_vosclose:
Pradeep Kumar Goudagunta22d8e4d2014-07-17 15:03:51 +05302302 if(!isSsrPanicOnFailure())
2303 {
2304 /* If we hit this, it means wlan driver is in bad state and needs
2305 * driver unload and load.
2306 */
Pradeep Kumar Goudagunta22d8e4d2014-07-17 15:03:51 +05302307 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE);
2308 return VOS_STATUS_E_FAILURE;
2309 }
2310
Jeff Johnson295189b2012-06-20 16:38:30 -07002311 vos_close(pVosContext);
2312 vos_sched_close(pVosContext);
2313 if (pHddCtx)
2314 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002315 /* Unregister the Net Device Notifier */
2316 unregister_netdevice_notifier(&hdd_netdev_notifier);
2317 /* Clean up HDD Nlink Service */
2318 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07002319#ifdef WLAN_KD_READY_NOTIFIER
2320 nl_srv_exit(pHddCtx->ptt_pid);
2321#else
Jeff Johnson295189b2012-06-20 16:38:30 -07002322 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07002323#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07002324 /* Free up dynamically allocated members inside HDD Adapter */
2325 kfree(pHddCtx->cfg_ini);
2326 pHddCtx->cfg_ini= NULL;
2327
Jeff Johnson295189b2012-06-20 16:38:30 -07002328 wiphy_unregister(pHddCtx->wiphy);
2329 wiphy_free(pHddCtx->wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07002330 }
2331 vos_preClose(&pVosContext);
2332
2333#ifdef MEMORY_DEBUG
2334 vos_mem_exit();
2335#endif
2336
2337err_re_init:
2338 /* Allow the phone to go to sleep */
Sushant Kaushik83392fa2015-05-05 17:44:40 +05302339 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT);
Sameer Thalappil9ab2fe52013-10-22 12:50:24 -07002340 vos_set_reinit_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07002341 VOS_BUG(0);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002342 return -EPERM;
Jeff Johnson295189b2012-06-20 16:38:30 -07002343
2344success:
2345 /* Trigger replay of BTC events */
2346 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
2347 return VOS_STATUS_SUCCESS;
2348}