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