blob: 6d96a86feb9e1045dc18f462476c8c578f4b1891 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Jeff Johnson32d95a32012-09-10 13:15:23 -07002 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -07003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/**=============================================================================
23* wlan_hdd_early_suspend.c
24*
25* \brief power management functions
26*
27* Description
28* Copyright 2009 (c) Qualcomm, Incorporated.
29* All Rights Reserved.
30* Qualcomm Confidential and Proprietary.
31*
32==============================================================================**/
33/* $HEADER$ */
34
35/**-----------------------------------------------------------------------------
36* Include files
37* ----------------------------------------------------------------------------*/
38#ifdef CONFIG_HAS_EARLYSUSPEND
39
40#include <linux/pm.h>
41#include <linux/wait.h>
42#include <linux/earlysuspend.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070043#include <wlan_hdd_includes.h>
44#include <wlan_qct_driver.h>
45#include <linux/wakelock.h>
46#endif
47
48#include "halTypes.h"
49#include "sme_Api.h"
50#include <vos_api.h>
51#include "vos_power.h"
52#include <vos_sched.h>
53#include <macInitApi.h>
54#ifdef ANI_BUS_TYPE_SDIO
55#include <wlan_qct_sal.h>
56#include <wlan_qct_bal.h>
57#endif
58#include <wlan_qct_sys.h>
59#include <wlan_btc_svc.h>
60#include <wlan_nlink_common.h>
61#include <wlan_hdd_main.h>
62#include <wlan_hdd_assoc.h>
63#include <wlan_hdd_dev_pwr.h>
64#ifdef ANI_BUS_TYPE_SDIO
65#include <wlan_sal_misc.h>
66#include <libra_sdioif.h>
67#endif
68#include <wlan_nlink_srv.h>
69#include <wlan_hdd_misc.h>
70
71#ifdef WLAN_SOFTAP_FEATURE
72#include <linux/semaphore.h>
73#include <wlan_hdd_hostapd.h>
74#endif
75#include "cfgApi.h"
76
77#ifdef WLAN_BTAMP_FEATURE
78#include "bapApi.h"
79#include "bap_hdd_main.h"
80#include "bap_hdd_misc.h"
81#endif
82
Jeff Johnsone7245742012-09-05 17:12:55 -070083#include <linux/wcnss_wlan.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070084#include <linux/inetdevice.h>
85#include <wlan_hdd_cfg.h>
86/**-----------------------------------------------------------------------------
87* Preprocessor definitions and constants
88* ----------------------------------------------------------------------------*/
89
90/**-----------------------------------------------------------------------------
91* Type declarations
92* ----------------------------------------------------------------------------*/
93
94/**-----------------------------------------------------------------------------
95* Function and variables declarations
96* ----------------------------------------------------------------------------*/
97#include "wlan_hdd_power.h"
98#include "wlan_hdd_packet_filtering.h"
99
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -0700100#define HDD_SSR_BRING_UP_TIME 10000
Jeff Johnson295189b2012-06-20 16:38:30 -0700101#ifdef CONFIG_HAS_EARLYSUSPEND
102static struct early_suspend wlan_early_suspend;
103#endif
104
105static eHalStatus g_full_pwr_status;
106static eHalStatus g_standby_status;
107
108extern VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx);
109extern VOS_STATUS vos_chipExitDeepSleepVREGHandler(
110 vos_call_status_type* status,
111 vos_power_cb_type callback,
112 v_PVOID_t user_data);
113extern void hdd_wlan_initial_scan(hdd_context_t *pHddCtx);
114void unregister_wlan_suspend(void);
115
116extern struct notifier_block hdd_netdev_notifier;
117#ifdef WLAN_SOFTAP_FEATURE
118extern tVOS_CON_MODE hdd_get_conparam ( void );
119#endif
120
121#ifdef WLAN_FEATURE_PACKET_FILTERING
Jeff Johnsone7245742012-09-05 17:12:55 -0700122extern void wlan_hdd_set_mc_addr_list(hdd_context_t *pHddCtx, v_U8_t set, v_U8_t sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700123#endif
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -0700124static struct timer_list ssr_timer;
125static bool ssr_timer_started;
Jeff Johnson295189b2012-06-20 16:38:30 -0700126
127//Callback invoked by PMC to report status of standby request
128void hdd_suspend_standby_cbk (void *callbackContext, eHalStatus status)
129{
130 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
131 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Standby status = %d", __func__, status);
132 g_standby_status = status;
133
134 if(eHAL_STATUS_SUCCESS == status)
135 {
136 pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY;
137 }
138 else
139 {
140 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__);
141 }
142
143 complete(&pHddCtx->standby_comp_var);
144}
145
146//Callback invoked by PMC to report status of full power request
147void hdd_suspend_full_pwr_callback(void *callbackContext, eHalStatus status)
148{
149 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
150 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Full Power status = %d", __func__, status);
151 g_full_pwr_status = status;
152
153 if(eHAL_STATUS_SUCCESS == status)
154 {
155 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
156 }
157 else
158 {
159 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
160 }
161
162 complete(&pHddCtx->full_pwr_comp_var);
163}
164
165eHalStatus hdd_exit_standby(hdd_context_t *pHddCtx)
166{
167 eHalStatus status = VOS_STATUS_SUCCESS;
168
169 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from standby",__func__);
170 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
171
172 g_full_pwr_status = eHAL_STATUS_FAILURE;
173 status = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback, pHddCtx,
174 eSME_FULL_PWR_NEEDED_BY_HDD);
175
176 if(status == eHAL_STATUS_PMC_PENDING)
177 {
178 //Block on a completion variable. Can't wait forever though
179 wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var,
180 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
181 status = g_full_pwr_status;
182 if(g_full_pwr_status != eHAL_STATUS_SUCCESS)
183 {
184 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
185 VOS_ASSERT(0);
186 goto failure;
187 }
188 }
189 else if(status != eHAL_STATUS_SUCCESS)
190 {
191 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d",
192 __func__, status);
193 VOS_ASSERT(0);
194 goto failure;
195 }
196 else
197 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
198
199failure:
200 //No blocking to reduce latency. No other device should be depending on WLAN
201 //to finish resume and WLAN won't be instantly on after resume
202 return status;
203}
204
205
206//Helper routine to put the chip into standby
207VOS_STATUS hdd_enter_standby(hdd_context_t *pHddCtx)
208{
209 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
210 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
211
212 //Disable IMPS/BMPS as we do not want the device to enter any power
213 //save mode on its own during suspend sequence
214 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
215 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
216
217 //Note we do not disable queues unnecessarily. Queues should already be disabled
218 //if STA is disconnected or the queue will be disabled as and when disconnect
219 //happens because of standby procedure.
220
221 //Ensure that device is in full power first. There is scope for optimization
222 //here especially in scenarios where PMC is already in IMPS or REQUEST_IMPS.
223 //Core s/w needs to be optimized to handle this. Until then we request full
224 //power before issuing request for standby.
225 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
226 g_full_pwr_status = eHAL_STATUS_FAILURE;
227 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback,
228 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
229
230 if(halStatus == eHAL_STATUS_PMC_PENDING)
231 {
232 //Block on a completion variable. Can't wait forever though
233 wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var,
234 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
235 if(g_full_pwr_status != eHAL_STATUS_SUCCESS)
236 {
237 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower Failed",__func__);
238 VOS_ASSERT(0);
239 vosStatus = VOS_STATUS_E_FAILURE;
240 goto failure;
241 }
242 }
243 else if(halStatus != eHAL_STATUS_SUCCESS)
244 {
245 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d",
246 __func__, halStatus);
247 VOS_ASSERT(0);
248 vosStatus = VOS_STATUS_E_FAILURE;
249 goto failure;
250 }
251
252 if(pHddCtx->hdd_mcastbcast_filter_set == TRUE) {
253 hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
254 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
255 }
256
257 //Request standby. Standby will cause the STA to disassociate first. TX queues
258 //will be disabled (by HDD) when STA disconnects. You do not want to disable TX
259 //queues here. Also do not assert if the failure code is eHAL_STATUS_PMC_NOT_NOW as PMC
260 //will send this failure code in case of concurrent sessions. Power Save cannot be supported
261 //when there are concurrent sessions.
262 INIT_COMPLETION(pHddCtx->standby_comp_var);
263 g_standby_status = eHAL_STATUS_FAILURE;
264 halStatus = sme_RequestStandby(pHddCtx->hHal, hdd_suspend_standby_cbk, pHddCtx);
265
266 if (halStatus == eHAL_STATUS_PMC_PENDING)
267 {
268 //Wait till WLAN device enters standby mode
269 wait_for_completion_timeout(&pHddCtx->standby_comp_var,
270 msecs_to_jiffies(WLAN_WAIT_TIME_STANDBY));
271 if (g_standby_status != eHAL_STATUS_SUCCESS && g_standby_status != eHAL_STATUS_PMC_NOT_NOW)
272 {
273 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__);
274 VOS_ASSERT(0);
275 vosStatus = VOS_STATUS_E_FAILURE;
276 goto failure;
277 }
278 }
279 else if (halStatus != eHAL_STATUS_SUCCESS && halStatus != eHAL_STATUS_PMC_NOT_NOW) {
280 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed - status %d",
281 __func__, halStatus);
282 VOS_ASSERT(0);
283 vosStatus = VOS_STATUS_E_FAILURE;
284 goto failure;
285 }
286 else
287 pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY;
288
289failure:
290 //Restore IMPS config
291 if(pHddCtx->cfg_ini->fIsImpsEnabled)
292 sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
293
294 //Restore BMPS config
295 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
296 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
297
298 return vosStatus;
299}
300
301
302//Helper routine for Deep sleep entry
303VOS_STATUS hdd_enter_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter)
304{
305 eHalStatus halStatus;
306 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
307 vos_call_status_type callType;
308#ifdef ANI_BUS_TYPE_SDIO
309 struct sdio_func *sdio_func_dev_current = NULL;
310 int attempts = 0;
311#endif
312 //Stop the Interface TX queue.
313 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
330 wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var,
331 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
332 if(g_full_pwr_status != eHAL_STATUS_SUCCESS){
333 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
334 VOS_ASSERT(0);
335 }
336 }
337 else if(halStatus != eHAL_STATUS_SUCCESS)
338 {
339 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Request for Full Power failed",__func__);
340 VOS_ASSERT(0);
341 }
342
343 //Issue a disconnect. This is required to inform the supplicant that
344 //STA is getting disassociated and for GUI to be updated properly
345 INIT_COMPLETION(pAdapter->disconnect_comp_var);
346 halStatus = sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED);
347
348 //Success implies disconnect command got queued up successfully
349 if(halStatus == eHAL_STATUS_SUCCESS)
350 {
351 //Block on a completion variable. Can't wait forever though.
352 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
353 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
354 }
355
356
357 //None of the steps should fail after this. Continue even in case of failure
358 vosStatus = vos_stop( pHddCtx->pvosContext );
359 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
360
361#ifdef ANI_BUS_TYPE_SDIO
362 vosStatus = WLANBAL_Stop( pHddCtx->pvosContext );
363 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
364
365 vosStatus = WLANBAL_SuspendChip( pHddCtx->pvosContext );
366 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
367
368 vosStatus = WLANSAL_Stop(pHddCtx->pvosContext);
369 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
370#endif
371
372 vosStatus = vos_chipAssertDeepSleep( &callType, NULL, NULL );
373 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
374
375 //Vote off any PMIC voltage supplies
376 vosStatus = vos_chipPowerDown(NULL, NULL, NULL);
377
378#ifdef ANI_BUS_TYPE_SDIO
379 //Get the Current SDIO Func
380 sdio_func_dev_current = libra_getsdio_funcdev();
381 if(NULL != sdio_func_dev_current) {
382 libra_detect_card_change();
383 do {
384 msleep(100);
385 //Get the SDIO func device
386 sdio_func_dev_current = libra_getsdio_funcdev();
387 if(NULL == sdio_func_dev_current) {
388 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Card Removed Successfully",__func__);
389 break;
390 }
391 else {
392 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to Remove the Card: Trying Again",__func__);
393 attempts++;
394 }
395 } while (attempts < LIBRA_CARD_REMOVE_DETECT_MAX_COUNT);
396
397 if(LIBRA_CARD_REMOVE_DETECT_MAX_COUNT == attempts) {
398 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to Remove the Card: Fatal",__func__);
399 goto err_fail;
400 }
401 }
402#endif
403
404 pHddCtx->hdd_ps_state = eHDD_SUSPEND_DEEP_SLEEP;
405
406 //Restore IMPS config
407 if(pHddCtx->cfg_ini->fIsImpsEnabled)
408 sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
409
410 //Restore BMPS config
411 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
412 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
413
414#ifdef ANI_BUS_TYPE_SDIO
415err_fail:
416#endif
417 return vosStatus;
418}
419
420VOS_STATUS hdd_exit_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter)
421{
422 VOS_STATUS vosStatus;
423 eHalStatus halStatus;
424#ifdef ANI_BUS_TYPE_SDIO
425 int attempts = 0;
426 struct sdio_func *sdio_func_dev = NULL;
427#endif
428
429 //Power Up Libra WLAN card first if not already powered up
430 vosStatus = vos_chipPowerUp(NULL,NULL,NULL);
431 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
432 {
433 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
434 "exiting", __func__);
435 goto err_deep_sleep;
436 }
437
438#ifdef ANI_BUS_TYPE_SDIO
439 libra_detect_card_change();
440
441 do {
442 sdio_func_dev = libra_getsdio_funcdev();
443 if (NULL == sdio_func_dev) {
444 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not detected yet.",__func__);
445 attempts++;
446 }
447 else {
448 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN detecton succeeded",__func__);
449 break;
450 }
451
452 if(LIBRA_CARD_INSERT_DETECT_MAX_COUNT == attempts)
453 break;
454
455 msleep(250);
456
457 }while (attempts < LIBRA_CARD_INSERT_DETECT_MAX_COUNT);
458
459 //Retry to detect the card again by Powering Down the chip and Power up the chip
460 //again. This retry is done to recover from CRC Error
461 if (NULL == sdio_func_dev) {
462
463 attempts = 0;
464
465 //Vote off any PMIC voltage supplies
466 vos_chipPowerDown(NULL, NULL, NULL);
467
468 msleep(1000);
469
470 //Power Up Libra WLAN card first if not already powered up
471 vosStatus = vos_chipPowerUp(NULL,NULL,NULL);
472 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
473 {
474 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not Powered Up. "
475 "exiting", __func__);
476 goto err_deep_sleep;
477 }
478
479 do {
480 sdio_func_dev = libra_getsdio_funcdev();
481 if (NULL == sdio_func_dev) {
482 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not detected yet.",__func__);
483 attempts++;
484 }
485 else {
486 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN detecton succeeded",__func__);
487 break;
488 }
489
490 if(attempts == 2)
491 break;
492
493 msleep(1000);
494
495 }while (attempts < 3);
496
497 }
498
499 if (NULL == sdio_func_dev) {
500 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not found!!",__func__);
501 goto err_deep_sleep;
502 }
503
504 SET_NETDEV_DEV(pAdapter->dev, &sdio_func_dev->dev);
505 libra_sdio_setprivdata (sdio_func_dev, pHddCtx);
506 atomic_set(&pHddCtx->sdio_claim_count, 0);
507 pHddCtx->parent_dev = &sdio_func_dev->dev;
508
509 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
510 "%s: calling WLANSAL_Start",__func__);
511 vosStatus = WLANSAL_Start(pHddCtx->pvosContext);
512 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
513 {
514 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
515 "%s: Failed to start SAL",__func__);
516 goto err_deep_sleep;
517 }
518
519 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
520 "%s: calling WLANBAL_ResumeChip",__func__);
521 vosStatus = WLANBAL_ResumeChip( pHddCtx->pvosContext );
522 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
523 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
524 {
525 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
526 "%s: Failed in WLANBAL_ResumeChip",__func__);
527 goto err_sal_stop;
528 }
529
530 vosStatus = WLANBAL_Start(pHddCtx->pvosContext);
531
532 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
533 {
534 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
535 "%s: Failed to start BAL",__func__);
536 goto err_sal_stop;
537 }
538#endif
539
540 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
541 "%s: calling hdd_set_sme_config",__func__);
542 vosStatus = hdd_set_sme_config( pHddCtx );
543 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
544 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
545 {
546 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
547 "%s: Failed in hdd_set_sme_config",__func__);
548#ifdef ANI_BUS_TYPE_SDIO
549 goto err_bal_stop;
550#else
551 goto err_deep_sleep;
552#endif
553 }
554
555 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
556 "%s: calling vos_start",__func__);
557 vosStatus = vos_start( pHddCtx->pvosContext );
558 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
559 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
560 {
561 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
562 "%s: Failed in vos_start",__func__);
563#ifdef ANI_BUS_TYPE_SDIO
564 goto err_bal_stop;
565#else
566 goto err_deep_sleep;
567#endif
568 }
569
570 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
571 "%s: calling hdd_post_voss_start_config",__func__);
572 vosStatus = hdd_post_voss_start_config( pHddCtx );
573 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
574 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
575 {
576 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
577 "%s: Failed in hdd_post_voss_start_config",__func__);
578 goto err_voss_stop;
579 }
580
581
582 //Open a SME session for future operation
583 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pHddCtx,
584 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
585 if ( !HAL_STATUS_SUCCESS( halStatus ) )
586 {
587 hddLog(VOS_TRACE_LEVEL_FATAL,"sme_OpenSession() failed with status code %08d [x%08lx]",
588 halStatus, halStatus );
589 goto err_voss_stop;
590
591 }
592
593 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
594
595 //Trigger the initial scan
596 hdd_wlan_initial_scan(pHddCtx);
597
598 return VOS_STATUS_SUCCESS;
599
600err_voss_stop:
601 vos_stop(pHddCtx->pvosContext);
602#ifdef ANI_BUS_TYPE_SDIO
603err_bal_stop:
604 WLANBAL_Stop(pHddCtx->pvosContext);
605err_sal_stop:
606 WLANSAL_Stop(pHddCtx->pvosContext);
607#endif
608err_deep_sleep:
609 return VOS_STATUS_E_FAILURE;
610
611}
612
613VOS_STATUS hdd_conf_hostarpoffload(hdd_context_t* pHddCtx, v_BOOL_t fenable)
614{
615 struct in_ifaddr **ifap = NULL;
616 struct in_ifaddr *ifa = NULL;
617 struct in_device *in_dev;
618 int i = 0;
619 hdd_adapter_t *pAdapter = NULL;
620 tSirHostOffloadReq offLoadRequest;
621
622 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: \n", __func__);
623#ifdef WLAN_FEATURE_PACKET_FILTERING
624 if (pHddCtx->cfg_ini->isMcAddrListFilter)
625 {
626 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
627 if (pAdapter != NULL)
628 {
629 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700630 "%s: Can't set multicast addr filtering in P2P-GO HDD", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700631 return VOS_STATUS_E_FAILURE;
632 }
633
634 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
635 if (pAdapter == NULL)
636 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
637
638 if(pAdapter == NULL)
639 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700640 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700641 return VOS_STATUS_E_FAILURE;
642 }
643 }
644 else
645 {
646#endif
647 pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_INFRA_STATION);
648 if(pAdapter == NULL)
649 {
650 pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_P2P_CLIENT);
651 if(pAdapter == NULL)
652 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700653 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700654 return VOS_STATUS_E_FAILURE;
655 }
656 }
657#ifdef WLAN_FEATURE_PACKET_FILTERING
658 }
659#endif
660 if(fenable)
661 {
662 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
663 {
664 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
665 ifap = &ifa->ifa_next)
666 {
667 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
668 {
669 break; /* found */
670 }
671 }
672 }
673
674 if(ifa && ifa->ifa_local)
675 {
676 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
677 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
678
679 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Enabled \n", __func__);
680
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700681 if(pHddCtx->dynamic_mcbc_filter.enableCfg)
Jeff Johnson295189b2012-06-20 16:38:30 -0700682 {
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700683 if((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
684 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting) ||
685 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
686 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting))
687 {
688 offLoadRequest.enableOrDisable =
689 SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
690 }
691 }
692 else if((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
693 pHddCtx->cfg_ini->mcastBcastFilterSetting ) ||
694 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
695 pHddCtx->cfg_ini->mcastBcastFilterSetting))
696 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700697 offLoadRequest.enableOrDisable =
698 SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
699 }
700
701 //converting u32 to IPV4 address
702 for(i = 0 ; i < 4; i++)
703 {
704 offLoadRequest.params.hostIpv4Addr[i] =
705 (ifa->ifa_local >> (i*8) ) & 0xFF ;
706 }
707 hddLog(VOS_TRACE_LEVEL_WARN, " Enable SME HostOffload: %d.%d.%d.%d",
708 offLoadRequest.params.hostIpv4Addr[0],
709 offLoadRequest.params.hostIpv4Addr[1],
710 offLoadRequest.params.hostIpv4Addr[2],
711 offLoadRequest.params.hostIpv4Addr[3]);
712
713 if (eHAL_STATUS_SUCCESS !=
Jeff Johnsone7245742012-09-05 17:12:55 -0700714 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
715 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700716 {
717 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to enable HostOffload "
718 "feature\n", __func__);
719 return VOS_STATUS_E_FAILURE;
720 }
721 return VOS_STATUS_SUCCESS;
722 }
723 else
724 {
725 hddLog(VOS_TRACE_LEVEL_INFO, "%s:IP Address is not assigned \n", __func__);
726 return VOS_STATUS_E_AGAIN;
727 }
728 }
729 else
730 {
731 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
732 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
733 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
734
Jeff Johnsone7245742012-09-05 17:12:55 -0700735 if (eHAL_STATUS_SUCCESS != sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
736 &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700737 {
738 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to disable host "
739 "offload feature\n", __func__);
740 return VOS_STATUS_E_FAILURE;
741 }
742 return VOS_STATUS_SUCCESS;
743 }
744}
745
746void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter)
747{
748 eHalStatus halStatus = eHAL_STATUS_FAILURE;
749#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
750 tpAniSirGlobal pMac = (tpAniSirGlobal) vos_get_context(VOS_MODULE_ID_SME, pHddCtx->pvosContext);
751#else
752 tpSirWlanSetRxpFilters wlanRxpFilterParam =
753 vos_mem_malloc(sizeof(tSirWlanSetRxpFilters));
754 if(NULL == wlanRxpFilterParam)
755 {
756 hddLog(VOS_TRACE_LEVEL_FATAL,
757 "%s: vos_mem_alloc failed ", __func__);
758 return;
759 }
760#endif
761 hddLog(VOS_TRACE_LEVEL_INFO,
762 "%s: Configuring Mcast/Bcast Filter Setting. setfilter %d", __func__, setfilter);
763#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
764 if ( pMac )
765 {
766 halStatus = halRxp_configureRxpFilterMcstBcst( pMac, setfilter);
767 }
768 else
769 {
770 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pMac is initialised to NULL",__func__ );
771 }
772#else
773 wlanRxpFilterParam->setMcstBcstFilter = setfilter;
774 wlanRxpFilterParam->configuredMcstBcstFilterSetting =
775 pHddCtx->cfg_ini->mcastBcastFilterSetting;
776 halStatus = sme_ConfigureRxpFilter(pHddCtx->hHal, wlanRxpFilterParam);
777#endif
778 if(setfilter && (eHAL_STATUS_SUCCESS == halStatus))
779 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
780}
781
Jeff Johnsone7245742012-09-05 17:12:55 -0700782#ifdef CONFIG_HAS_EARLYSUSPEND
Jeff Johnson295189b2012-06-20 16:38:30 -0700783#ifdef FEATURE_WLAN_INTEGRATED_SOC
784static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx,
785 hdd_adapter_t *pAdapter)
786{
787 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Madan Mohan Koyyalamudi51d87f72012-09-24 12:05:23 -0700788 VOS_STATUS vstatus = VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700789 tpSirWlanSuspendParam wlanSuspendParam =
790 vos_mem_malloc(sizeof(tSirWlanSuspendParam));
791
792 if(NULL == wlanSuspendParam)
793 {
794 hddLog(VOS_TRACE_LEVEL_FATAL,
795 "%s: vos_mem_alloc failed ", __func__);
796 return;
797 }
798
799 hddLog(VOS_TRACE_LEVEL_INFO,
800 "%s: send wlan suspend indication", __func__);
801
802 if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER))
803 {
804 if((pHddCtx->cfg_ini->fhostArpOffload) &&
805 (eConnectionState_Associated ==
806 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
807 {
Jeff Johnson43971f52012-07-17 12:26:56 -0700808 vstatus = hdd_conf_hostarpoffload(pHddCtx, TRUE);
809 if (!VOS_IS_STATUS_SUCCESS(vstatus))
Jeff Johnson295189b2012-06-20 16:38:30 -0700810 {
Jeff Johnson43971f52012-07-17 12:26:56 -0700811 if(pHddCtx->dynamic_mcbc_filter.enableCfg)
812 {
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700813 wlanSuspendParam->configuredMcstBcstFilterSetting =
814 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting;
815 pHddCtx->dynamic_mcbc_filter.enableSuspend = TRUE;
Jeff Johnson43971f52012-07-17 12:26:56 -0700816 }
817 else
818 {
819 wlanSuspendParam->configuredMcstBcstFilterSetting =
820 pHddCtx->cfg_ini->mcastBcastFilterSetting;
821 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700822 hddLog(VOS_TRACE_LEVEL_INFO,
823 "%s:Failed to enable ARPOFFLOAD Feature %d\n",
Jeff Johnson43971f52012-07-17 12:26:56 -0700824 __func__, vstatus);
Jeff Johnson295189b2012-06-20 16:38:30 -0700825 }
Jeff Johnson43971f52012-07-17 12:26:56 -0700826 else
827 {
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700828 if(pHddCtx->dynamic_mcbc_filter.enableCfg)
829 {
830 if((HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
831 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting))
832 {
833 wlanSuspendParam->configuredMcstBcstFilterSetting =
834 HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST;
835 }
836 else if((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
837 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting))
838 {
839 wlanSuspendParam->configuredMcstBcstFilterSetting =
840 HDD_MCASTBCASTFILTER_FILTER_NONE;
841 }
842 else
843 {
844 wlanSuspendParam->configuredMcstBcstFilterSetting =
845 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting;
846 }
847
848 pHddCtx->dynamic_mcbc_filter.enableSuspend = TRUE;
849 pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend =
850 wlanSuspendParam->configuredMcstBcstFilterSetting;
851 }
852 else
853 {
854 if (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
855 pHddCtx->cfg_ini->mcastBcastFilterSetting)
856 {
857 wlanSuspendParam->configuredMcstBcstFilterSetting =
858 HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST;
859 }
860 else if(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
861 pHddCtx->cfg_ini->mcastBcastFilterSetting)
862 {
863 wlanSuspendParam->configuredMcstBcstFilterSetting =
864 HDD_MCASTBCASTFILTER_FILTER_NONE;
865 }
866 else
867 {
868 wlanSuspendParam->configuredMcstBcstFilterSetting =
869 pHddCtx->cfg_ini->mcastBcastFilterSetting;
870 }
871
872 pHddCtx->dynamic_mcbc_filter.enableSuspend = FALSE;
873 }
874 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700875 }
876 else
877 {
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700878 if(pHddCtx->dynamic_mcbc_filter.enableCfg)
879 {
880 wlanSuspendParam->configuredMcstBcstFilterSetting =
Jeff Johnson43971f52012-07-17 12:26:56 -0700881 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting;
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700882 pHddCtx->dynamic_mcbc_filter.enableSuspend = TRUE;
883 pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend =
Jeff Johnson43971f52012-07-17 12:26:56 -0700884 wlanSuspendParam->configuredMcstBcstFilterSetting;
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700885 }
886 else
887 {
888 pHddCtx->dynamic_mcbc_filter.enableSuspend = FALSE;
889 wlanSuspendParam->configuredMcstBcstFilterSetting =
890 pHddCtx->cfg_ini->mcastBcastFilterSetting;
891 }
892 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700893
894#ifdef WLAN_FEATURE_PACKET_FILTERING
895 if (pHddCtx->cfg_ini->isMcAddrListFilter)
896 {
897 /*Multicast addr list filter is enabled during suspend*/
898 if (((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
899 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT))
900 && pHddCtx->mc_addr_list.mc_cnt
901 && (eConnectionState_Associated ==
902 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
903 {
904 /*set the filter*/
Jeff Johnsone7245742012-09-05 17:12:55 -0700905 wlan_hdd_set_mc_addr_list(pHddCtx, TRUE, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700906 }
907 }
908#endif
909 }
910
911 halStatus = sme_ConfigureSuspendInd(pHddCtx->hHal, wlanSuspendParam);
912 if(eHAL_STATUS_SUCCESS == halStatus)
913 {
914 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
915 }
916}
917
Jeff Johnsone7245742012-09-05 17:12:55 -0700918static void hdd_conf_resume_ind(hdd_context_t* pHddCtx, v_U8_t sessionId)
Jeff Johnson295189b2012-06-20 16:38:30 -0700919{
Jeff Johnson43971f52012-07-17 12:26:56 -0700920 VOS_STATUS vstatus;
Jeff Johnson295189b2012-06-20 16:38:30 -0700921 tpSirWlanResumeParam wlanResumeParam =
922 vos_mem_malloc(sizeof(tSirWlanResumeParam));
923
924 if(NULL == wlanResumeParam)
925 {
926 hddLog(VOS_TRACE_LEVEL_FATAL,
927 "%s: vos_mem_alloc failed ", __func__);
928 return;
929 }
930
931 hddLog(VOS_TRACE_LEVEL_INFO,
932 "%s: send wlan resume indication", __func__);
933
934 if(pHddCtx->cfg_ini->fhostArpOffload)
935 {
Jeff Johnson43971f52012-07-17 12:26:56 -0700936 vstatus = hdd_conf_hostarpoffload(pHddCtx, FALSE);
937 if (!VOS_IS_STATUS_SUCCESS(vstatus))
Jeff Johnson295189b2012-06-20 16:38:30 -0700938 {
939 hddLog(VOS_TRACE_LEVEL_INFO, "%s:Failed to disable ARPOFFLOAD "
Jeff Johnson43971f52012-07-17 12:26:56 -0700940 "Feature %d\n", __func__, vstatus);
Jeff Johnson295189b2012-06-20 16:38:30 -0700941 }
942 }
943 if (pHddCtx->dynamic_mcbc_filter.enableSuspend)
944 {
945 wlanResumeParam->configuredMcstBcstFilterSetting =
946 pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend;
947 }
948 else
949 {
950 wlanResumeParam->configuredMcstBcstFilterSetting =
951 pHddCtx->cfg_ini->mcastBcastFilterSetting;
952 }
953 sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam);
954
955#ifdef WLAN_FEATURE_PACKET_FILTERING
956 if (pHddCtx->cfg_ini->isMcAddrListFilter)
957 {
958 /*Mutlicast addr filtering is enabled*/
959 if(pHddCtx->mc_addr_list.isFilterApplied)
960 {
961 /*Filter applied during suspend mode*/
962 /*Clear it here*/
Jeff Johnsone7245742012-09-05 17:12:55 -0700963 wlan_hdd_set_mc_addr_list(pHddCtx, FALSE, sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700964 }
965 }
966#endif
967}
968#endif
969
Jeff Johnson295189b2012-06-20 16:38:30 -0700970//Suspend routine registered with Android OS
971void hdd_suspend_wlan(struct early_suspend *wlan_suspend)
972{
973 hdd_context_t *pHddCtx = NULL;
974 v_CONTEXT_t pVosContext = NULL;
975
976 hdd_adapter_t *pAdapter = NULL;
977 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
978 VOS_STATUS status;
979#ifdef ANI_BUS_TYPE_SDIO
980 struct sdio_func *sdio_func_dev = NULL;
981#endif
982 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__);
983
984 //Get the global VOSS context.
985 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
986 if(!pVosContext) {
987 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
988 return;
989 }
990
991 //Get the HDD context.
992 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
993
994 if(!pHddCtx) {
995 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
996 return;
997 }
998
999 if (pHddCtx->isLogpInProgress) {
1000 hddLog(VOS_TRACE_LEVEL_ERROR,
1001 "%s: Ignore suspend wlan, LOGP in progress!", __func__);
1002 return;
1003 }
1004
1005#ifdef ANI_BUS_TYPE_SDIO
1006 sdio_func_dev = libra_getsdio_funcdev();
1007
1008 if(sdio_func_dev == NULL)
1009 {
1010 /* Our card got removed */
1011 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
1012 return;
1013 }
1014
1015 if(!sd_is_drvdata_available(sdio_func_dev))
1016 {
1017 /* Our card got removed */
1018 hddLog(VOS_TRACE_LEVEL_FATAL,
1019 "%s: HDD context is not available in sdio_func_dev!",__func__);
1020 return;
1021 }
1022
1023 sd_claim_host(sdio_func_dev);
1024
1025 // Prevent touching the pMac while LOGP reset in progress, we should never get here
1026 // as the wake lock is already acquired and it would prevent from entering suspend
1027 if (pHddCtx->isLogpInProgress) {
1028 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Ignore suspend wlan, LOGP in progress!", __func__);
1029 sd_release_host(sdio_func_dev);
1030 return;
1031 }
1032#endif
1033
1034 /*loop through all adapters. TBD fix for Concurrency */
1035 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1036 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1037 {
1038 pAdapter = pAdapterNode->pAdapter;
1039 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001040 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001041 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
1042
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001043 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001044 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1045 pAdapterNode = pNext;
1046 continue;
1047 }
1048
1049#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1050 if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1051 {
1052 //stop the interface before putting the chip to standby
1053 netif_tx_disable(pAdapter->dev);
1054 netif_carrier_off(pAdapter->dev);
1055 }
1056 else if (pHddCtx->cfg_ini->nEnableSuspend ==
1057 WLAN_MAP_SUSPEND_TO_DEEP_SLEEP)
1058 {
1059 //Execute deep sleep procedure
1060 hdd_enter_deep_sleep(pHddCtx, pAdapter);
1061 }
1062#endif
1063
Jeff Johnsone7245742012-09-05 17:12:55 -07001064 //Apply Dynamic Dtim For P2P
1065 //Only if ignoreDynamicDtimInP2pMode is not set in ini
Jeff Johnson295189b2012-06-20 16:38:30 -07001066 if((pHddCtx->cfg_ini->enableDynamicDTIM ||
Jeff Johnsone7245742012-09-05 17:12:55 -07001067 pHddCtx->cfg_ini->enableModulatedDTIM) &&
1068 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
1069 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
1070 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07001071 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
1072 (eConnectionState_Associated ==
1073 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
1074 (pHddCtx->cfg_ini->fIsBmpsEnabled))
1075 {
1076 tSirSetPowerParamsReq powerRequest = { 0 };
1077
1078 powerRequest.uIgnoreDTIM = 1;
1079
1080 /*Back up the actual values from CFG */
1081 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM,
1082 &pHddCtx->hdd_actual_ignore_DTIM_value);
1083 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL,
1084 &pHddCtx->hdd_actual_LI_value);
1085
1086 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1087 {
1088 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
1089 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
1090 }
1091 else
1092 {
1093 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
1094 }
1095
1096 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
1097 *specified during Enter/Exit BMPS when LCD off*/
1098 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1099 NULL, eANI_BOOLEAN_FALSE);
1100 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1101 NULL, eANI_BOOLEAN_FALSE);
1102
1103 /* switch to the DTIM specified in cfg.ini */
1104 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1105 "Switch to DTIM%d \n", powerRequest.uListenInterval);
1106 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest);
1107
1108 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
1109 {
1110 /* put the device into full power */
1111 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
1112
1113 /* put the device back into BMPS */
1114 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
1115
1116 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1117 }
1118 }
1119
1120#ifdef FEATURE_WLAN_INTEGRATED_SOC
1121 /*Suspend notification sent down to driver*/
1122 hdd_conf_suspend_ind(pHddCtx, pAdapter);
1123#else
1124 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER) {
1125 if(eConnectionState_Associated ==
1126 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) {
1127 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
1128 halPSAppsCpuWakeupState(vos_get_context(VOS_MODULE_ID_SME,
1129 pHddCtx->pvosContext), FALSE);
1130 }
1131 }
1132#endif
1133 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1134 pAdapterNode = pNext;
1135 }
1136 pHddCtx->hdd_wlan_suspended = TRUE;
1137
1138#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1139 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1140 {
1141 hdd_enter_standby(pHddCtx);
1142 }
1143#endif
1144#ifdef ANI_BUS_TYPE_SDIO
1145 sd_release_host(sdio_func_dev);
1146#endif
1147
1148 return;
1149}
1150
1151static void hdd_PowerStateChangedCB
1152(
1153 v_PVOID_t callbackContext,
1154 tPmcState newState
1155)
1156{
1157 hdd_context_t *pHddCtx = callbackContext;
1158
1159 /* if the driver was not in BMPS during early suspend,
1160 * the dynamic DTIM is now updated at Riva */
1161 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended
1162 && pHddCtx->cfg_ini->enableDynamicDTIM
1163 && (pHddCtx->hdd_ignore_dtim_enabled == FALSE))
1164 {
1165 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1166 }
1167 spin_lock(&pHddCtx->filter_lock);
1168 if((newState == BMPS) && pHddCtx->hdd_wlan_suspended
1169 && (pHddCtx->hdd_mcastbcast_filter_set != TRUE)) {
1170 spin_unlock(&pHddCtx->filter_lock);
1171 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
1172#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
1173 halPSAppsCpuWakeupState(vos_get_context(VOS_MODULE_ID_SME, pHddCtx->pvosContext), FALSE);
1174#endif
1175 if(pHddCtx->hdd_mcastbcast_filter_set != TRUE)
1176 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__);
1177 }
1178 else
1179 spin_unlock(&pHddCtx->filter_lock);
1180}
1181
1182
1183
1184void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx)
1185{
1186 v_CONTEXT_t pVosContext;
1187 tHalHandle smeContext;
1188
1189 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1190 if (NULL == pVosContext)
1191 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001192 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001193 return;
1194 }
1195 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1196 if (NULL == smeContext)
1197 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001198 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001199 return;
1200 }
1201
1202 spin_lock_init(&pHddCtx->filter_lock);
1203 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1204 pHddCtx->cfg_ini->nEnableSuspend)
1205 {
1206 pmcRegisterDeviceStateUpdateInd(smeContext,
1207 hdd_PowerStateChangedCB, pHddCtx);
1208 }
1209}
1210
1211void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx)
1212{
1213 v_CONTEXT_t pVosContext;
1214 tHalHandle smeContext;
1215
1216 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1217 if (NULL == pVosContext)
1218 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001219 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001220 return;
1221 }
1222 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1223 if (NULL == smeContext)
1224 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001225 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001226 return;
1227 }
1228
1229 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1230 pHddCtx->cfg_ini->nEnableSuspend)
1231 {
1232 pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB);
1233 }
1234}
1235
1236void hdd_resume_wlan(struct early_suspend *wlan_suspend)
1237{
1238 hdd_context_t *pHddCtx = NULL;
1239 hdd_adapter_t *pAdapter = NULL;
1240 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1241 VOS_STATUS status;
1242 v_CONTEXT_t pVosContext = NULL;
1243#ifdef ANI_BUS_TYPE_SDIO
1244 struct sdio_func *sdio_func_dev = NULL;
1245#endif
1246 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
1247
1248 //Get the global VOSS context.
1249 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1250 if(!pVosContext) {
1251 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1252 return;
1253 }
1254
1255 //Get the HDD context.
1256 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1257
1258 if(!pHddCtx) {
1259 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1260 return;
1261 }
1262
1263 if (pHddCtx->isLogpInProgress) {
1264 hddLog(VOS_TRACE_LEVEL_INFO,
1265 "%s: Ignore resume wlan, LOGP in progress!", __func__);
1266 return;
1267 }
1268
1269#ifdef ANI_BUS_TYPE_SDIO
1270 sdio_func_dev = libra_getsdio_funcdev();
1271
1272 if(sdio_func_dev == NULL)
1273 {
1274 /* Our card got removed */
1275 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
1276 return;
1277 }
1278
1279 if(!sd_is_drvdata_available(sdio_func_dev))
1280 {
1281 /* Our card got removed */
1282 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD context is not available "
1283 "in sdio_func_dev!",__func__);
1284 return;
1285 }
1286
1287 sd_claim_host(sdio_func_dev);
1288
1289 // Prevent touching the pMac while LOGP reset in progress,
1290 if (pHddCtx->isLogpInProgress) {
1291 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Ignore resume wlan, LOGP in progress!", __func__);
1292 sd_release_host(sdio_func_dev);
1293 return;
1294 }
1295#endif
1296 pHddCtx->hdd_wlan_suspended = FALSE;
1297 /*loop through all adapters. Concurrency */
1298 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1299
1300 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1301 {
1302 pAdapter = pAdapterNode->pAdapter;
1303 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001304 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001305 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001306 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001307 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1308 pAdapterNode = pNext;
1309 continue;
1310 }
1311#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1312 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP)
1313 {
1314 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__);
1315 hdd_exit_deep_sleep(pAdapter);
1316 }
1317#endif
1318
1319 if(pHddCtx->hdd_ignore_dtim_enabled == TRUE)
1320 {
1321 /*Switch back to DTIM 1*/
1322 tSirSetPowerParamsReq powerRequest = { 0 };
1323
1324 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
1325 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
1326
1327 /*Disabled ModulatedDTIM if enabled on suspend*/
1328 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1329 powerRequest.uDTIMPeriod = 0;
1330
1331 /* Update ignoreDTIM and ListedInterval in CFG with default values */
1332 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1333 NULL, eANI_BOOLEAN_FALSE);
1334 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1335 NULL, eANI_BOOLEAN_FALSE);
1336
1337 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1338 "Switch to DTIM%d \n",powerRequest.uListenInterval);
1339 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest);
1340
1341 /* put the device into full power */
1342 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
1343
1344 /* put the device back into BMPS */
1345 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
1346
1347 pHddCtx->hdd_ignore_dtim_enabled = FALSE;
1348 }
1349
1350 if(pHddCtx->hdd_mcastbcast_filter_set == TRUE) {
1351#ifdef FEATURE_WLAN_INTEGRATED_SOC
Jeff Johnsone7245742012-09-05 17:12:55 -07001352 hdd_conf_resume_ind(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001353#else
1354 hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
1355 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
1356 halPSAppsCpuWakeupState(vos_get_context(VOS_MODULE_ID_SME,
1357 pHddCtx->pvosContext), TRUE);
1358#endif
1359 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
1360 }
1361 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1362 pAdapterNode = pNext;
1363 }
1364
1365#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1366 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY)
1367 {
1368 hdd_exit_standby(pHddCtx);
1369 }
1370#endif
1371
1372#ifdef ANI_BUS_TYPE_SDIO
1373 sd_release_host(sdio_func_dev);
1374#endif
1375 return;
1376}
1377
1378VOS_STATUS hdd_wlan_reset(void)
1379{
1380 VOS_STATUS vosStatus;
1381 hdd_context_t *pHddCtx = NULL;
1382 v_CONTEXT_t pVosContext = NULL;
1383 pVosSchedContext vosSchedContext = NULL;
1384#ifdef ANI_BUS_TYPE_SDIO
1385 struct sdio_func *sdio_func_dev_new = NULL;
1386 struct sdio_func *sdio_func_dev_current = NULL;
1387 unsigned int attempts = 0;
1388#endif
1389 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1390
1391 //Get the global VOSS context.
1392 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1393 if(!pVosContext) {
1394 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1395 return VOS_STATUS_E_FAILURE;
1396 }
1397
1398 //Get the HDD context.
1399 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1400 if(!pHddCtx) {
1401 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1402 return VOS_STATUS_E_FAILURE;
1403 }
1404#ifdef ANI_BUS_TYPE_SDIO
1405 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SAL Stop",__func__);
1406 //Invoke SAL stop
1407 vosStatus = WLANSAL_Stop( pVosContext );
1408 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1409 {
1410 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1411 "%s: Failed to stop SAL",__func__);
1412 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1413 }
1414#endif
1415 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Asserting Deep Sleep",__func__);
1416 //Assert Deep sleep signal now to put Libra HW in lowest power state
1417 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
1418 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1419
1420 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Power Down Chip",__func__);
1421 //Vote off any PMIC voltage supplies
1422 vos_chipPowerDown(NULL, NULL, NULL);
1423
1424
1425 /**
1426 EVM issue is observed with 1.6Mhz freq for 1.3V supply in wlan standalone case.
1427 During concurrent operation (e.g. WLAN and WCDMA) this issue is not observed.
1428 To workaround, wlan will vote for 3.2Mhz during startup and will vote for 1.6Mhz
1429 during exit.
1430 */
1431 if (vos_chipVoteFreqFor1p3VSupply(NULL, NULL, NULL, VOS_NV_FREQUENCY_FOR_1_3V_SUPPLY_1P6MH) != VOS_STATUS_SUCCESS)
1432 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1433 "%s: Failed to set the freq to 1.6Mhz for 1.3V Supply",__func__ );
1434
1435 //Disable IMPS/BMPS as we do not want the device to enter any power
1436 //save mode on its own during reset sequence
1437 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1438 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1439 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1440
1441 //Kill all the threads first. We do not want any messages
1442 //to be a processed any more and the best way to ensure that
1443 //is to terminate the threads gracefully.
1444 vosSchedContext = get_vos_sched_ctxt();
1445
1446 /* Wakeup Mc Thread if Suspended */
1447 if(TRUE == pHddCtx->isMcThreadSuspended){
1448 complete(&vosSchedContext->ResumeMcEvent);
1449 pHddCtx->isMcThreadSuspended= FALSE;
1450 }
1451 /* Wakeup Tx Thread if Suspended */
1452 if(TRUE == pHddCtx->isTxThreadSuspended){
1453 complete(&vosSchedContext->ResumeTxEvent);
1454 pHddCtx->isTxThreadSuspended= FALSE;
1455 }
1456#ifdef FEATURE_WLAN_INTEGRATED_SOC
1457 /* Wakeup Rx Thread if Suspended */
1458 if(TRUE == pHddCtx->isRxThreadSuspended){
1459 complete(&vosSchedContext->ResumeRxEvent);
1460 pHddCtx->isRxThreadSuspended= FALSE;
1461 }
1462#endif
1463
1464 /* Reset the Suspend Variable */
1465 pHddCtx->isWlanSuspended = FALSE;
1466
1467 //Wait for MC to exit
1468 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
1469 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
1470 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
1471 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
1472 wait_for_completion_interruptible(&vosSchedContext->McShutdown);
1473
1474 //Wait for TX to exit
1475 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
1476 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
1477 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
1478 wake_up_interruptible(&vosSchedContext->txWaitQueue);
1479 wait_for_completion_interruptible(&vosSchedContext->TxShutdown);
1480
1481#ifdef FEATURE_WLAN_INTEGRATED_SOC
1482 //Wait for RX to exit
1483 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
1484 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
1485 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
1486 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
1487 wait_for_completion_interruptible(&vosSchedContext->RxShutdown);
1488#endif
1489
1490 /* Cancel the vote for XO Core ON in LOGP since we are reinitializing our driver
1491 * This is done here to ensure there is no race condition since MC and TX thread have
1492 * exited at this point
1493 */
1494 hddLog(VOS_TRACE_LEVEL_WARN, "In LOGP: Cancel XO Core ON vote\n");
1495 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
1496 {
1497 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
1498 "Power consumed will be high\n");
1499 }
1500
1501 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
1502 //Stop SME - Cannot invoke vos_stop as vos_stop relies
1503 //on threads being running to process the SYS Stop
1504 vosStatus = sme_Stop( pHddCtx->hHal, TRUE );
1505 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1506
1507 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
1508 //Stop MAC (PE and HAL)
1509 vosStatus = macStop( pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
1510 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1511
1512 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
1513 //Stop TL
1514 vosStatus = WLANTL_Stop( pVosContext );
1515 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1516
1517#ifdef ANI_BUS_TYPE_SDIO
1518 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing BAL STOP",__func__);
1519 vosStatus = WLANBAL_Stop( pVosContext );
1520 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1521 {
1522 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1523 "%s: Failed to stop BAL",__func__);
1524 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1525 }
1526#endif
1527#ifdef CONFIG_HAS_EARLYSUSPEND
1528 hdd_unregister_mcast_bcast_filter(pHddCtx);
1529#endif
1530
1531 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Flush Queues",__func__);
1532 //Clean up message queues of TX and MC thread
1533 vos_sched_flush_mc_mqs(vosSchedContext);
1534 vos_sched_flush_tx_mqs(vosSchedContext);
1535#ifdef FEATURE_WLAN_INTEGRATED_SOC
1536 vos_sched_flush_rx_mqs(vosSchedContext);
1537#endif
1538
1539 //Deinit all the TX and MC queues
1540 vos_sched_deinit_mqs(vosSchedContext);
1541
1542 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing VOS Close",__func__);
1543
1544 //Close VOSS
1545 vos_close(pVosContext);
1546
1547#ifdef ANI_BUS_TYPE_SDIO
1548 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing BAL Close",__func__);
1549 vosStatus = WLANBAL_Close(pVosContext);
1550 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1551 {
1552 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1553 "%s: Failed to close BAL",__func__);
1554 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1555 }
1556 //Get the Current SDIO Func
1557 sdio_func_dev_current = libra_getsdio_funcdev();
1558
1559 if(NULL != sdio_func_dev_current) {
1560 libra_detect_card_change();
1561 attempts = 0;
1562 do {
1563 msleep(100);
1564 //Get the SDIO func device
1565 sdio_func_dev_current = libra_getsdio_funcdev();
1566 if(NULL == sdio_func_dev_current) {
1567 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Card Removed Successfully",__func__);
1568 break;
1569 }
1570 else {
1571 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to Remove the Card: Trying Again",__func__);
1572 attempts++;
1573 }
1574 } while (attempts < LIBRA_CARD_REMOVE_DETECT_MAX_COUNT);
1575
1576 if(LIBRA_CARD_REMOVE_DETECT_MAX_COUNT == attempts) {
1577 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to Remove the Card: Fatal",__func__);
1578 goto err_fail;
1579 }
1580 }
1581#endif
1582
1583#ifdef TIMER_MANAGER
1584 vos_timer_exit();
1585#endif
1586
1587#ifdef MEMORY_DEBUG
1588 vos_mem_clean();
1589#endif
1590#ifdef ANI_BUS_TYPE_SDIO
1591 //Reinitialize the variable
1592 attempts = 0;
1593#endif
1594
1595 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Powering Up chip Again",__func__);
1596 //Power Up Libra WLAN card first if not already powered up
1597 vosStatus = vos_chipPowerUp(NULL,NULL,NULL);
1598 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1599 {
1600 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
1601 "exiting", __func__);
1602 goto err_pwr_fail;
1603 }
1604
1605#ifdef ANI_BUS_TYPE_SDIO
1606 // Trigger card detect
1607 libra_detect_card_change();
1608
1609 //Reinitialize the variable
1610 attempts = 0;
1611
1612 do {
1613 msleep(500);
1614
1615 //Get the SDIO func device
1616 sdio_func_dev_new = libra_getsdio_funcdev();
1617 if(sdio_func_dev_new != NULL)
1618 {
1619 //Not needed but in case it causes probs then put a loop and set for each adapter
1620 //SET_NETDEV_DEV(pAdapter->dev, &sdio_func_dev_new->dev);
1621 libra_sdio_setprivdata (sdio_func_dev_new, pHddCtx);
1622 atomic_set(&pHddCtx->sdio_claim_count, 0);
1623 pHddCtx->parent_dev = &sdio_func_dev_new->dev;
1624 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1625 "%s: Card Detected Successfully %p",__func__,
1626 sdio_func_dev_new);
1627 break;
1628 }
1629 else
1630 {
1631 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1632 "%s: Failed to detect card change %p",__func__,
1633 sdio_func_dev_new);
1634 attempts++;
1635 }
1636 }while (attempts < LIBRA_CARD_INSERT_DETECT_MAX_COUNT);
1637
1638 if(LIBRA_CARD_INSERT_DETECT_MAX_COUNT == attempts){
1639 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN fail to detect in reset, "
1640 "exiting", __func__);
1641 goto err_fail;
1642 }
1643 //Get the SDIO func device
1644 sdio_func_dev_new = libra_getsdio_funcdev();
1645 if(sdio_func_dev_new != NULL)
1646 {
1647 sd_claim_host(sdio_func_dev_new);
1648 /* Enable IRQ capabilities in host controller */
1649 libra_disable_sdio_irq_capability(sdio_func_dev_new, 0);
1650 libra_enable_sdio_irq(sdio_func_dev_new, 1);
1651 sd_release_host(sdio_func_dev_new);
1652 }
1653 else
1654 {
1655 /* Our card got removed before LOGP. */
1656 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
1657 goto err_fail;
1658 }
1659
1660 vosStatus = WLANBAL_Open(pVosContext);
1661 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1662 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1663 {
1664 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1665 "%s: Failed to open BAL",__func__);
1666 goto err_fail;
1667 }
1668
1669 vosStatus = WLANSAL_Start(pVosContext);
1670 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1671 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1672 {
1673 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to start SAL",__func__);
1674 goto err_balclose;
1675 }
1676
1677 /* Chip is reset so allow Lower MAC to start accessing WLAN registers. Note HDD is still blocked */
1678 vos_set_logp_in_progress(VOS_MODULE_ID_HDD, FALSE);
1679
1680 /* Start BAL */
1681 vosStatus = WLANBAL_Start(pVosContext);
1682
1683 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1684 {
1685 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1686 "%s: Failed to start BAL",__func__);
1687 goto err_salstop;
1688 }
1689#endif
1690 // Open VOSS
1691 vosStatus = vos_open( &pVosContext, 0);
1692
1693 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
1694 {
1695 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
1696#ifdef ANI_BUS_TYPE_SDIO
1697 goto err_balstop;
1698#else
1699 goto err_pwr_fail;
1700#endif
1701 }
1702
1703 /* Save the hal context in Adapter */
1704 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
1705
1706 if ( NULL == pHddCtx->hHal )
1707 {
1708 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
1709 goto err_vosclose;
1710 }
1711 // Set the SME configuration parameters...
1712 vosStatus = hdd_set_sme_config(pHddCtx);
1713
1714 if ( VOS_STATUS_SUCCESS != vosStatus )
1715 {
1716 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
1717 goto err_vosclose;
1718 }
1719
1720 //Initialize the WMM module
1721 vosStatus = hdd_wmm_init(pHddCtx);
1722 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
1723 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001724 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001725 goto err_vosclose;
1726 }
1727
1728 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
1729 Note: Firmware image will be read and downloaded inside vos_start API */
1730 vosStatus = vos_start( pVosContext );
1731 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1732 {
1733 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
1734 goto err_vosclose;
1735 }
1736
1737 vosStatus = hdd_post_voss_start_config( pHddCtx );
1738 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1739 {
1740 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
1741 __func__);
1742 goto err_vosstop;
1743 }
1744
1745 /* Restart all adapters */
1746 hdd_start_all_adapters(pHddCtx);
1747 pHddCtx->isLogpInProgress = FALSE;
1748 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
1749#ifdef CONFIG_HAS_EARLYSUSPEND
1750 hdd_register_mcast_bcast_filter(pHddCtx);
1751#endif
1752
1753 // Allow the phone to go to sleep
1754 hdd_allow_suspend();
1755
1756 goto success;
1757
1758err_vosstop:
1759 vos_stop(pVosContext);
1760
1761err_vosclose:
1762 vos_close(pVosContext );
1763 vos_sched_close(pVosContext);
1764
1765#ifdef ANI_BUS_TYPE_SDIO
1766err_balstop:
1767#ifndef ANI_MANF_DIAG
1768 wlan_hdd_enable_deepsleep(pVosContext);
1769#endif
1770 WLANBAL_Stop(pVosContext);
1771 WLANBAL_SuspendChip(pVosContext);
1772
1773err_salstop:
1774 WLANSAL_Stop(pVosContext);
1775
1776err_balclose:
1777 WLANBAL_Close(pVosContext);
1778
1779err_fail:
1780 //Assert Deep sleep signal now to put Libra HW in lowest power state
1781 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
1782
1783 //Vote off any PMIC voltage supplies
1784 vos_chipPowerDown(NULL, NULL, NULL);
1785#endif
1786
1787err_pwr_fail:
1788 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
1789
1790 // Allow the phone to go to sleep
1791 hdd_allow_suspend();
1792
1793#ifdef CONFIG_HAS_EARLYSUSPEND
1794 // unregister suspend/resume callbacks
1795 if(pHddCtx->cfg_ini->nEnableSuspend)
1796 unregister_wlan_suspend();
1797#endif
1798
1799 // Unregister the Net Device Notifier
1800 unregister_netdevice_notifier(&hdd_netdev_notifier);
1801
1802 //Clean up HDD Nlink Service
1803 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1804 nl_srv_exit();
1805
1806 hdd_close_all_adapters(pHddCtx);
1807 //Free up dynamically allocated members inside HDD Adapter
1808 kfree(pHddCtx->cfg_ini);
1809 pHddCtx->cfg_ini= NULL;
1810
1811#ifdef CONFIG_CFG80211
1812 wiphy_unregister(pHddCtx->wiphy);
1813 wiphy_free(pHddCtx->wiphy);
1814#else
1815 vos_mem_free(pHddCtx);
1816#endif
1817
1818#ifdef ANI_BUS_TYPE_SDIO
1819 WLANSAL_Close(pVosContext);
1820#endif
1821 vos_preClose(&pVosContext);
1822
1823#ifdef MEMORY_DEBUG
1824 vos_mem_exit();
1825#endif
1826
1827 return -1;
1828
1829success:
1830 //Trigger replay of BTC events
1831 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1832 return VOS_STATUS_SUCCESS;
1833
1834}
1835
1836
1837
1838VOS_STATUS hdd_wlan_reset_initialization(void)
1839{
1840#ifdef ANI_BUS_TYPE_SDIO
1841 struct sdio_func *sdio_func_dev = NULL;
1842 v_U8_t regValue = 0;
1843 int err_ret = 0;
1844#endif
1845 v_CONTEXT_t pVosContext = NULL;
1846
1847 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1848
1849 //Get the global VOSS context.
1850 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1851 if(!pVosContext)
1852 {
1853 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1854 return VOS_STATUS_E_FAILURE;
1855 }
1856
1857 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__);
1858
1859 // Prevent the phone from going to sleep
1860 hdd_prevent_suspend();
1861
1862#ifdef ANI_BUS_TYPE_SDIO
1863 /* Clear pending interrupt and disable Interrupts. Use only CMD52 */
1864 VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
1865 "%s LOGP in progress. Disabling Interrupt", __func__);
1866
1867 sdio_func_dev = libra_getsdio_funcdev();
1868
1869 if(sdio_func_dev == NULL)
1870 {
1871 /* Our card got removed before LOGP. Continue with reset anyways */
1872 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
1873 return VOS_STATUS_SUCCESS;
1874 }
1875
1876 sd_claim_host(sdio_func_dev);
1877
1878 regValue = 0;
1879 libra_sdiocmd52(sdio_func_dev, QWLAN_SIF_SIF_INT_EN_REG,
1880 &regValue, 1, &err_ret);
1881
1882 VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
1883 "%s LOGP Cleared SIF_SIF_INT_EN_REG status:%d", __func__,err_ret);
1884
1885 regValue = 0;
1886 libra_sdiocmd52(sdio_func_dev, QWLAN_SIF_BAR4_INT_PEND_REG,
1887 &regValue, 1, &err_ret);
1888
1889 VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
1890 "%s LOGP Cleared SIF_BAR4_INT_PEND_REG status :%d", __func__,err_ret);
1891
1892 regValue = 0;
1893 libra_sdiocmd52(sdio_func_dev, QWLAN_SIF_BAR4_INT_ENABLE_REG,
1894 &regValue, 1, &err_ret);
1895
1896 VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
1897 "%s LOGP Cleared SIF_BAR4_INT_ENABLE_REG: Status:%d", __func__,err_ret);
1898
1899 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing Suspend Chip",__func__);
1900
1901 //Put the chip is standby before asserting deep sleep
1902 WLANBAL_SuspendChip_NoLock( pVosContext );
1903
1904 sd_release_host(sdio_func_dev);
1905#endif
1906
1907 return VOS_STATUS_SUCCESS;
1908}
1909
1910
1911void register_wlan_suspend(void)
1912{
1913 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Register WLAN suspend/resume "
1914 "callbacks",__func__);
1915 wlan_early_suspend.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING;
1916 wlan_early_suspend.suspend = hdd_suspend_wlan;
1917 wlan_early_suspend.resume = hdd_resume_wlan;
1918 register_early_suspend(&wlan_early_suspend);
1919}
1920
1921void unregister_wlan_suspend(void)
1922{
1923 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Unregister WLAN suspend/resume "
1924 "callbacks",__func__);
1925 unregister_early_suspend(&wlan_early_suspend);
1926}
1927#endif
1928
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001929static void hdd_ssr_timer_init(void)
1930{
1931 init_timer(&ssr_timer);
1932}
1933static void hdd_ssr_timer_del(void)
1934{
1935 del_timer(&ssr_timer);
1936 ssr_timer_started = false;
1937}
1938static void hdd_ssr_timer_cb(unsigned long data)
1939{
1940 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD SSR timer expired", __func__);
1941 VOS_BUG(0);
1942}
1943static void hdd_ssr_timer_start(int msec)
1944{
1945 if(ssr_timer_started)
1946 {
1947 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: trying to start SSR timer when it's running"
1948 ,__func__);
1949 }
1950 ssr_timer.expires = jiffies + msecs_to_jiffies(msec);
1951 ssr_timer.function = hdd_ssr_timer_cb;
1952 add_timer(&ssr_timer);
1953 ssr_timer_started = true;
1954}
Jeff Johnson295189b2012-06-20 16:38:30 -07001955/* the HDD interface to WLAN driver shutdown,
1956 * the primary shutdown function in SSR
1957 */
1958VOS_STATUS hdd_wlan_shutdown(void)
1959{
1960 VOS_STATUS vosStatus;
1961 v_CONTEXT_t pVosContext = NULL;
1962 hdd_context_t *pHddCtx = NULL;
1963 pVosSchedContext vosSchedContext = NULL;
1964
1965 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__);
1966
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001967 /* if re-init never happens, then do SSR1 */
1968 hdd_ssr_timer_init();
1969 hdd_ssr_timer_start(HDD_SSR_BRING_UP_TIME);
1970
Jeff Johnson295189b2012-06-20 16:38:30 -07001971 /* Get the global VOSS context. */
1972 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1973 if(!pVosContext) {
1974 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1975 return VOS_STATUS_E_FAILURE;
1976 }
1977 /* Get the HDD context. */
1978 pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1979 if(!pHddCtx) {
1980 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1981 return VOS_STATUS_E_FAILURE;
1982 }
1983 hdd_reset_all_adapters(pHddCtx);
1984#ifdef CONFIG_HAS_EARLYSUSPEND
1985 /* unregister suspend/resume callbacks */
1986 if(pHddCtx->cfg_ini->nEnableSuspend)
1987 {
1988 unregister_wlan_suspend();
1989 }
1990#endif
1991 /* DeRegister with platform driver as client for Suspend/Resume */
1992 vosStatus = hddDeregisterPmOps(pHddCtx);
1993 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1994 {
1995 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
1996 }
1997
1998 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
1999 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2000 {
2001 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
2002 }
2003
2004 /* Disable IMPS/BMPS as we do not want the device to enter any power
2005 * save mode on its own during reset sequence
2006 */
2007 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2008 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2009 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
2010
2011 vosSchedContext = get_vos_sched_ctxt();
2012
2013 /* Wakeup all driver threads */
2014 if(TRUE == pHddCtx->isMcThreadSuspended){
2015 complete(&vosSchedContext->ResumeMcEvent);
2016 pHddCtx->isMcThreadSuspended= FALSE;
2017 }
2018 if(TRUE == pHddCtx->isTxThreadSuspended){
2019 complete(&vosSchedContext->ResumeTxEvent);
2020 pHddCtx->isTxThreadSuspended= FALSE;
2021 }
2022 if(TRUE == pHddCtx->isRxThreadSuspended){
2023 complete(&vosSchedContext->ResumeRxEvent);
2024 pHddCtx->isRxThreadSuspended= FALSE;
2025 }
2026 /* Reset the Suspend Variable */
2027 pHddCtx->isWlanSuspended = FALSE;
2028
2029 /* Stop all the threads; we do not want any messages to be a processed,
2030 * any more and the best way to ensure that is to terminate the threads
2031 * gracefully.
2032 */
2033 /* Wait for MC to exit */
2034 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
2035 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
2036 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
2037 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
2038 wait_for_completion_interruptible(&vosSchedContext->McShutdown);
2039
2040 /* Wait for TX to exit */
2041 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
2042 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
2043 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
2044 wake_up_interruptible(&vosSchedContext->txWaitQueue);
2045 wait_for_completion_interruptible(&vosSchedContext->TxShutdown);
2046
2047 /* Wait for RX to exit */
2048 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
2049 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
2050 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
2051 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
2052 wait_for_completion_interruptible(&vosSchedContext->RxShutdown);
2053
2054#ifdef WLAN_BTAMP_FEATURE
2055 vosStatus = WLANBAP_Stop(pVosContext);
2056 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2057 {
2058 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2059 "%s: Failed to stop BAP",__func__);
2060 }
2061#endif //WLAN_BTAMP_FEATURE
2062 vosStatus = vos_wda_shutdown(pVosContext);
2063 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
2064
2065 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
2066 /* Stop SME - Cannot invoke vos_stop as vos_stop relies
2067 * on threads being running to process the SYS Stop
2068 */
2069 vosStatus = sme_Stop(pHddCtx->hHal, TRUE);
2070 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
2071
2072 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
2073 /* Stop MAC (PE and HAL) */
2074 vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
2075 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
2076
2077 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
2078 /* Stop TL */
2079 vosStatus = WLANTL_Stop(pVosContext);
2080 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
2081
2082#ifdef CONFIG_HAS_EARLYSUSPEND
2083 hdd_unregister_mcast_bcast_filter(pHddCtx);
2084#endif
2085 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__);
2086 /* Clean up message queues of TX and MC thread */
2087 vos_sched_flush_mc_mqs(vosSchedContext);
2088 vos_sched_flush_tx_mqs(vosSchedContext);
2089 vos_sched_flush_rx_mqs(vosSchedContext);
2090
2091 /* Deinit all the TX and MC queues */
2092 vos_sched_deinit_mqs(vosSchedContext);
2093 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__);
2094
2095 /* shutdown VOSS */
2096 vos_shutdown(pVosContext);
2097 if (free_riva_power_on_lock("wlan"))
2098 {
2099 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
2100 __func__);
2101 }
2102 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete"
2103 ,__func__);
2104 return VOS_STATUS_SUCCESS;
2105}
2106
2107
2108
2109/* the HDD interface to WLAN driver re-init.
2110 * This is called to initialize/start WLAN driver after a shutdown.
2111 */
2112VOS_STATUS hdd_wlan_re_init(void)
2113{
2114 VOS_STATUS vosStatus;
2115 v_CONTEXT_t pVosContext = NULL;
2116 hdd_context_t *pHddCtx = NULL;
2117 eHalStatus halStatus;
2118#ifdef WLAN_BTAMP_FEATURE
2119 hdd_config_t *pConfig = NULL;
2120 WLANBAP_ConfigType btAmpConfig;
2121#endif
2122
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07002123 hdd_ssr_timer_del();
Jeff Johnson295189b2012-06-20 16:38:30 -07002124 hdd_prevent_suspend();
2125 /* Re-open VOSS, it is a re-open b'se control transport was never closed. */
2126 vosStatus = vos_open(&pVosContext, 0);
2127 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2128 {
2129 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
2130 goto err_re_init;
2131 }
2132
2133 /* Get the HDD context. */
2134 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
2135 if(!pHddCtx)
2136 {
2137 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
2138 goto err_vosclose;
2139 }
2140
2141 /* Save the hal context in Adapter */
2142 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
2143 if ( NULL == pHddCtx->hHal )
2144 {
2145 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
2146 goto err_vosclose;
2147 }
2148
2149 /* Set the SME configuration parameters. */
2150 vosStatus = hdd_set_sme_config(pHddCtx);
2151 if ( VOS_STATUS_SUCCESS != vosStatus )
2152 {
2153 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
2154 goto err_vosclose;
2155 }
2156
2157 /* Initialize the WMM module */
2158 vosStatus = hdd_wmm_init(pHddCtx);
2159 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
2160 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002161 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002162 goto err_vosclose;
2163 }
2164
2165 vosStatus = vos_preStart( pHddCtx->pvosContext );
2166 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2167 {
2168 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
2169 goto err_vosclose;
2170 }
2171
2172 /* In the integrated architecture we update the configuration from
2173 the INI file and from NV before vOSS has been started so that
2174 the final contents are available to send down to the cCPU */
2175 /* Apply the cfg.ini to cfg.dat */
2176 if (FALSE == hdd_update_config_dat(pHddCtx))
2177 {
2178 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
2179 goto err_vosclose;
2180 }
2181
2182 /* Set the MAC Address, currently this is used by HAL to add self sta.
2183 * Remove this once self sta is added as part of session open. */
2184 halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID,
2185 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
2186 sizeof(pHddCtx->cfg_ini->intfMacAddr[0]));
2187 if (!HAL_STATUS_SUCCESS(halStatus))
2188 {
2189 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
2190 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus);
2191 goto err_vosclose;
2192 }
2193
2194 /* Start VOSS which starts up the SME/MAC/HAL modules and everything else
2195 Note: Firmware image will be read and downloaded inside vos_start API */
2196 vosStatus = vos_start( pVosContext );
2197 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2198 {
2199 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
2200 goto err_vosclose;
2201 }
2202
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07002203 /* Exchange capability info between Host and FW and also get versioning info from FW */
2204 hdd_exchange_version_and_caps(pHddCtx);
2205
Jeff Johnson295189b2012-06-20 16:38:30 -07002206 vosStatus = hdd_post_voss_start_config( pHddCtx );
2207 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2208 {
2209 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
2210 __func__);
2211 goto err_vosstop;
2212 }
2213
2214#ifdef WLAN_BTAMP_FEATURE
2215 vosStatus = WLANBAP_Open(pVosContext);
2216 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
2217 {
2218 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2219 "%s: Failed to open BAP",__func__);
2220 goto err_vosstop;
2221 }
2222 vosStatus = BSL_Init(pVosContext);
2223 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
2224 {
2225 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2226 "%s: Failed to Init BSL",__func__);
2227 goto err_bap_close;
2228 }
2229 vosStatus = WLANBAP_Start(pVosContext);
2230 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2231 {
2232 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2233 "%s: Failed to start TL",__func__);
2234 goto err_bap_close;
2235 }
2236 pConfig = pHddCtx->cfg_ini;
2237 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
2238 vosStatus = WLANBAP_SetConfig(&btAmpConfig);
2239#endif //WLAN_BTAMP_FEATURE
2240
2241 /* Restart all adapters */
2242 hdd_start_all_adapters(pHddCtx);
2243 pHddCtx->isLogpInProgress = FALSE;
2244 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
2245#ifdef CONFIG_HAS_EARLYSUSPEND
2246 hdd_register_mcast_bcast_filter(pHddCtx);
2247#endif
2248
2249 /* Register with platform driver as client for Suspend/Resume */
2250 vosStatus = hddRegisterPmOps(pHddCtx);
2251 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2252 {
2253 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
2254 goto err_bap_stop;
2255 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002256#ifdef CONFIG_HAS_EARLYSUSPEND
Jeff Johnson295189b2012-06-20 16:38:30 -07002257 // Register suspend/resume callbacks
2258 if(pHddCtx->cfg_ini->nEnableSuspend)
2259 {
2260 register_wlan_suspend();
2261 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002262#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002263 /* Allow the phone to go to sleep */
2264 hdd_allow_suspend();
2265 /* register for riva power on lock */
2266 if (req_riva_power_on_lock("wlan"))
2267 {
2268 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
2269 __func__);
2270 goto err_unregister_pmops;
2271 }
2272 goto success;
2273
2274err_unregister_pmops:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002275#ifdef CONFIG_HAS_EARLYSUSPEND
2276 /* unregister suspend/resume callbacks */
2277 if (pHddCtx->cfg_ini->nEnableSuspend)
2278 unregister_wlan_suspend();
2279#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002280 hddDeregisterPmOps(pHddCtx);
2281
2282err_bap_stop:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002283#ifdef CONFIG_HAS_EARLYSUSPEND
2284 hdd_unregister_mcast_bcast_filter(pHddCtx);
2285#endif
2286 hdd_close_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002287#ifdef WLAN_BTAMP_FEATURE
Jeff Johnson32d95a32012-09-10 13:15:23 -07002288 WLANBAP_Stop(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07002289#endif
2290
2291#ifdef WLAN_BTAMP_FEATURE
2292err_bap_close:
2293 WLANBAP_Close(pVosContext);
2294#endif
2295
2296err_vosstop:
2297 vos_stop(pVosContext);
2298
2299err_vosclose:
2300 vos_close(pVosContext);
2301 vos_sched_close(pVosContext);
2302 if (pHddCtx)
2303 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002304 /* Unregister the Net Device Notifier */
2305 unregister_netdevice_notifier(&hdd_netdev_notifier);
2306 /* Clean up HDD Nlink Service */
2307 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
2308 nl_srv_exit();
Jeff Johnson295189b2012-06-20 16:38:30 -07002309 /* Free up dynamically allocated members inside HDD Adapter */
2310 kfree(pHddCtx->cfg_ini);
2311 pHddCtx->cfg_ini= NULL;
2312
2313#ifdef CONFIG_CFG80211
2314 wiphy_unregister(pHddCtx->wiphy);
2315 wiphy_free(pHddCtx->wiphy);
2316#else
2317 vos_mem_free(pHddCtx);
2318#endif
2319 }
2320 vos_preClose(&pVosContext);
2321
2322#ifdef MEMORY_DEBUG
2323 vos_mem_exit();
2324#endif
2325
2326err_re_init:
2327 /* Allow the phone to go to sleep */
2328 hdd_allow_suspend();
2329 return -1;
2330
2331success:
2332 /* Trigger replay of BTC events */
2333 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
2334 return VOS_STATUS_SUCCESS;
2335}