blob: e23e20555359558f0d501fc99ae6ec50a43a278f [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,
630 "%s: Can't set multicast addr filtering in P2P-GO HDD", __FUNCTION__);
631 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 {
640 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __FUNCTION__);
641 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 {
653 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __FUNCTION__);
654 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)
1040 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
1041
1042 { //just do for station interface
1043 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1044 pAdapterNode = pNext;
1045 continue;
1046 }
1047
1048#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1049 if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1050 {
1051 //stop the interface before putting the chip to standby
1052 netif_tx_disable(pAdapter->dev);
1053 netif_carrier_off(pAdapter->dev);
1054 }
1055 else if (pHddCtx->cfg_ini->nEnableSuspend ==
1056 WLAN_MAP_SUSPEND_TO_DEEP_SLEEP)
1057 {
1058 //Execute deep sleep procedure
1059 hdd_enter_deep_sleep(pHddCtx, pAdapter);
1060 }
1061#endif
1062
Jeff Johnsone7245742012-09-05 17:12:55 -07001063 //Apply Dynamic Dtim For P2P
1064 //Only if ignoreDynamicDtimInP2pMode is not set in ini
Jeff Johnson295189b2012-06-20 16:38:30 -07001065 if((pHddCtx->cfg_ini->enableDynamicDTIM ||
Jeff Johnsone7245742012-09-05 17:12:55 -07001066 pHddCtx->cfg_ini->enableModulatedDTIM) &&
1067 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
1068 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
1069 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07001070 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
1071 (eConnectionState_Associated ==
1072 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
1073 (pHddCtx->cfg_ini->fIsBmpsEnabled))
1074 {
1075 tSirSetPowerParamsReq powerRequest = { 0 };
1076
1077 powerRequest.uIgnoreDTIM = 1;
1078
1079 /*Back up the actual values from CFG */
1080 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM,
1081 &pHddCtx->hdd_actual_ignore_DTIM_value);
1082 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL,
1083 &pHddCtx->hdd_actual_LI_value);
1084
1085 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1086 {
1087 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
1088 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
1089 }
1090 else
1091 {
1092 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
1093 }
1094
1095 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
1096 *specified during Enter/Exit BMPS when LCD off*/
1097 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1098 NULL, eANI_BOOLEAN_FALSE);
1099 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1100 NULL, eANI_BOOLEAN_FALSE);
1101
1102 /* switch to the DTIM specified in cfg.ini */
1103 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1104 "Switch to DTIM%d \n", powerRequest.uListenInterval);
1105 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest);
1106
1107 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
1108 {
1109 /* put the device into full power */
1110 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
1111
1112 /* put the device back into BMPS */
1113 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
1114
1115 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1116 }
1117 }
1118
1119#ifdef FEATURE_WLAN_INTEGRATED_SOC
1120 /*Suspend notification sent down to driver*/
1121 hdd_conf_suspend_ind(pHddCtx, pAdapter);
1122#else
1123 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER) {
1124 if(eConnectionState_Associated ==
1125 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) {
1126 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
1127 halPSAppsCpuWakeupState(vos_get_context(VOS_MODULE_ID_SME,
1128 pHddCtx->pvosContext), FALSE);
1129 }
1130 }
1131#endif
1132 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1133 pAdapterNode = pNext;
1134 }
1135 pHddCtx->hdd_wlan_suspended = TRUE;
1136
1137#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1138 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1139 {
1140 hdd_enter_standby(pHddCtx);
1141 }
1142#endif
1143#ifdef ANI_BUS_TYPE_SDIO
1144 sd_release_host(sdio_func_dev);
1145#endif
1146
1147 return;
1148}
1149
1150static void hdd_PowerStateChangedCB
1151(
1152 v_PVOID_t callbackContext,
1153 tPmcState newState
1154)
1155{
1156 hdd_context_t *pHddCtx = callbackContext;
1157
1158 /* if the driver was not in BMPS during early suspend,
1159 * the dynamic DTIM is now updated at Riva */
1160 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended
1161 && pHddCtx->cfg_ini->enableDynamicDTIM
1162 && (pHddCtx->hdd_ignore_dtim_enabled == FALSE))
1163 {
1164 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1165 }
1166 spin_lock(&pHddCtx->filter_lock);
1167 if((newState == BMPS) && pHddCtx->hdd_wlan_suspended
1168 && (pHddCtx->hdd_mcastbcast_filter_set != TRUE)) {
1169 spin_unlock(&pHddCtx->filter_lock);
1170 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
1171#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
1172 halPSAppsCpuWakeupState(vos_get_context(VOS_MODULE_ID_SME, pHddCtx->pvosContext), FALSE);
1173#endif
1174 if(pHddCtx->hdd_mcastbcast_filter_set != TRUE)
1175 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__);
1176 }
1177 else
1178 spin_unlock(&pHddCtx->filter_lock);
1179}
1180
1181
1182
1183void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx)
1184{
1185 v_CONTEXT_t pVosContext;
1186 tHalHandle smeContext;
1187
1188 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1189 if (NULL == pVosContext)
1190 {
1191 hddLog(LOGE, "%s: Invalid pContext", __FUNCTION__);
1192 return;
1193 }
1194 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1195 if (NULL == smeContext)
1196 {
1197 hddLog(LOGE, "%s: Invalid smeContext", __FUNCTION__);
1198 return;
1199 }
1200
1201 spin_lock_init(&pHddCtx->filter_lock);
1202 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1203 pHddCtx->cfg_ini->nEnableSuspend)
1204 {
1205 pmcRegisterDeviceStateUpdateInd(smeContext,
1206 hdd_PowerStateChangedCB, pHddCtx);
1207 }
1208}
1209
1210void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx)
1211{
1212 v_CONTEXT_t pVosContext;
1213 tHalHandle smeContext;
1214
1215 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1216 if (NULL == pVosContext)
1217 {
1218 hddLog(LOGE, "%s: Invalid pContext", __FUNCTION__);
1219 return;
1220 }
1221 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1222 if (NULL == smeContext)
1223 {
1224 hddLog(LOGE, "%s: Invalid smeContext", __FUNCTION__);
1225 return;
1226 }
1227
1228 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1229 pHddCtx->cfg_ini->nEnableSuspend)
1230 {
1231 pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB);
1232 }
1233}
1234
1235void hdd_resume_wlan(struct early_suspend *wlan_suspend)
1236{
1237 hdd_context_t *pHddCtx = NULL;
1238 hdd_adapter_t *pAdapter = NULL;
1239 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1240 VOS_STATUS status;
1241 v_CONTEXT_t pVosContext = NULL;
1242#ifdef ANI_BUS_TYPE_SDIO
1243 struct sdio_func *sdio_func_dev = NULL;
1244#endif
1245 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
1246
1247 //Get the global VOSS context.
1248 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1249 if(!pVosContext) {
1250 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1251 return;
1252 }
1253
1254 //Get the HDD context.
1255 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1256
1257 if(!pHddCtx) {
1258 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1259 return;
1260 }
1261
1262 if (pHddCtx->isLogpInProgress) {
1263 hddLog(VOS_TRACE_LEVEL_INFO,
1264 "%s: Ignore resume wlan, LOGP in progress!", __func__);
1265 return;
1266 }
1267
1268#ifdef ANI_BUS_TYPE_SDIO
1269 sdio_func_dev = libra_getsdio_funcdev();
1270
1271 if(sdio_func_dev == NULL)
1272 {
1273 /* Our card got removed */
1274 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
1275 return;
1276 }
1277
1278 if(!sd_is_drvdata_available(sdio_func_dev))
1279 {
1280 /* Our card got removed */
1281 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD context is not available "
1282 "in sdio_func_dev!",__func__);
1283 return;
1284 }
1285
1286 sd_claim_host(sdio_func_dev);
1287
1288 // Prevent touching the pMac while LOGP reset in progress,
1289 if (pHddCtx->isLogpInProgress) {
1290 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Ignore resume wlan, LOGP in progress!", __func__);
1291 sd_release_host(sdio_func_dev);
1292 return;
1293 }
1294#endif
1295 pHddCtx->hdd_wlan_suspended = FALSE;
1296 /*loop through all adapters. Concurrency */
1297 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1298
1299 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1300 {
1301 pAdapter = pAdapterNode->pAdapter;
1302 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
1303 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
1304 { //just do for station interface
1305 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1306 pAdapterNode = pNext;
1307 continue;
1308 }
1309#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1310 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP)
1311 {
1312 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__);
1313 hdd_exit_deep_sleep(pAdapter);
1314 }
1315#endif
1316
1317 if(pHddCtx->hdd_ignore_dtim_enabled == TRUE)
1318 {
1319 /*Switch back to DTIM 1*/
1320 tSirSetPowerParamsReq powerRequest = { 0 };
1321
1322 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
1323 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
1324
1325 /*Disabled ModulatedDTIM if enabled on suspend*/
1326 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1327 powerRequest.uDTIMPeriod = 0;
1328
1329 /* Update ignoreDTIM and ListedInterval in CFG with default values */
1330 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1331 NULL, eANI_BOOLEAN_FALSE);
1332 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1333 NULL, eANI_BOOLEAN_FALSE);
1334
1335 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1336 "Switch to DTIM%d \n",powerRequest.uListenInterval);
1337 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest);
1338
1339 /* put the device into full power */
1340 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
1341
1342 /* put the device back into BMPS */
1343 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
1344
1345 pHddCtx->hdd_ignore_dtim_enabled = FALSE;
1346 }
1347
1348 if(pHddCtx->hdd_mcastbcast_filter_set == TRUE) {
1349#ifdef FEATURE_WLAN_INTEGRATED_SOC
Jeff Johnsone7245742012-09-05 17:12:55 -07001350 hdd_conf_resume_ind(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001351#else
1352 hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
1353 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
1354 halPSAppsCpuWakeupState(vos_get_context(VOS_MODULE_ID_SME,
1355 pHddCtx->pvosContext), TRUE);
1356#endif
1357 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
1358 }
1359 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1360 pAdapterNode = pNext;
1361 }
1362
1363#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1364 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY)
1365 {
1366 hdd_exit_standby(pHddCtx);
1367 }
1368#endif
1369
1370#ifdef ANI_BUS_TYPE_SDIO
1371 sd_release_host(sdio_func_dev);
1372#endif
1373 return;
1374}
1375
1376VOS_STATUS hdd_wlan_reset(void)
1377{
1378 VOS_STATUS vosStatus;
1379 hdd_context_t *pHddCtx = NULL;
1380 v_CONTEXT_t pVosContext = NULL;
1381 pVosSchedContext vosSchedContext = NULL;
1382#ifdef ANI_BUS_TYPE_SDIO
1383 struct sdio_func *sdio_func_dev_new = NULL;
1384 struct sdio_func *sdio_func_dev_current = NULL;
1385 unsigned int attempts = 0;
1386#endif
1387 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1388
1389 //Get the global VOSS context.
1390 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1391 if(!pVosContext) {
1392 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1393 return VOS_STATUS_E_FAILURE;
1394 }
1395
1396 //Get the HDD context.
1397 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1398 if(!pHddCtx) {
1399 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1400 return VOS_STATUS_E_FAILURE;
1401 }
1402#ifdef ANI_BUS_TYPE_SDIO
1403 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SAL Stop",__func__);
1404 //Invoke SAL stop
1405 vosStatus = WLANSAL_Stop( pVosContext );
1406 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1407 {
1408 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1409 "%s: Failed to stop SAL",__func__);
1410 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1411 }
1412#endif
1413 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Asserting Deep Sleep",__func__);
1414 //Assert Deep sleep signal now to put Libra HW in lowest power state
1415 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
1416 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1417
1418 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Power Down Chip",__func__);
1419 //Vote off any PMIC voltage supplies
1420 vos_chipPowerDown(NULL, NULL, NULL);
1421
1422
1423 /**
1424 EVM issue is observed with 1.6Mhz freq for 1.3V supply in wlan standalone case.
1425 During concurrent operation (e.g. WLAN and WCDMA) this issue is not observed.
1426 To workaround, wlan will vote for 3.2Mhz during startup and will vote for 1.6Mhz
1427 during exit.
1428 */
1429 if (vos_chipVoteFreqFor1p3VSupply(NULL, NULL, NULL, VOS_NV_FREQUENCY_FOR_1_3V_SUPPLY_1P6MH) != VOS_STATUS_SUCCESS)
1430 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1431 "%s: Failed to set the freq to 1.6Mhz for 1.3V Supply",__func__ );
1432
1433 //Disable IMPS/BMPS as we do not want the device to enter any power
1434 //save mode on its own during reset sequence
1435 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1436 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1437 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1438
1439 //Kill all the threads first. We do not want any messages
1440 //to be a processed any more and the best way to ensure that
1441 //is to terminate the threads gracefully.
1442 vosSchedContext = get_vos_sched_ctxt();
1443
1444 /* Wakeup Mc Thread if Suspended */
1445 if(TRUE == pHddCtx->isMcThreadSuspended){
1446 complete(&vosSchedContext->ResumeMcEvent);
1447 pHddCtx->isMcThreadSuspended= FALSE;
1448 }
1449 /* Wakeup Tx Thread if Suspended */
1450 if(TRUE == pHddCtx->isTxThreadSuspended){
1451 complete(&vosSchedContext->ResumeTxEvent);
1452 pHddCtx->isTxThreadSuspended= FALSE;
1453 }
1454#ifdef FEATURE_WLAN_INTEGRATED_SOC
1455 /* Wakeup Rx Thread if Suspended */
1456 if(TRUE == pHddCtx->isRxThreadSuspended){
1457 complete(&vosSchedContext->ResumeRxEvent);
1458 pHddCtx->isRxThreadSuspended= FALSE;
1459 }
1460#endif
1461
1462 /* Reset the Suspend Variable */
1463 pHddCtx->isWlanSuspended = FALSE;
1464
1465 //Wait for MC to exit
1466 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
1467 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
1468 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
1469 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
1470 wait_for_completion_interruptible(&vosSchedContext->McShutdown);
1471
1472 //Wait for TX to exit
1473 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
1474 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
1475 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
1476 wake_up_interruptible(&vosSchedContext->txWaitQueue);
1477 wait_for_completion_interruptible(&vosSchedContext->TxShutdown);
1478
1479#ifdef FEATURE_WLAN_INTEGRATED_SOC
1480 //Wait for RX to exit
1481 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
1482 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
1483 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
1484 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
1485 wait_for_completion_interruptible(&vosSchedContext->RxShutdown);
1486#endif
1487
1488 /* Cancel the vote for XO Core ON in LOGP since we are reinitializing our driver
1489 * This is done here to ensure there is no race condition since MC and TX thread have
1490 * exited at this point
1491 */
1492 hddLog(VOS_TRACE_LEVEL_WARN, "In LOGP: Cancel XO Core ON vote\n");
1493 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
1494 {
1495 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
1496 "Power consumed will be high\n");
1497 }
1498
1499 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
1500 //Stop SME - Cannot invoke vos_stop as vos_stop relies
1501 //on threads being running to process the SYS Stop
1502 vosStatus = sme_Stop( pHddCtx->hHal, TRUE );
1503 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1504
1505 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
1506 //Stop MAC (PE and HAL)
1507 vosStatus = macStop( pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
1508 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1509
1510 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
1511 //Stop TL
1512 vosStatus = WLANTL_Stop( pVosContext );
1513 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1514
1515#ifdef ANI_BUS_TYPE_SDIO
1516 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing BAL STOP",__func__);
1517 vosStatus = WLANBAL_Stop( pVosContext );
1518 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1519 {
1520 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1521 "%s: Failed to stop BAL",__func__);
1522 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1523 }
1524#endif
1525#ifdef CONFIG_HAS_EARLYSUSPEND
1526 hdd_unregister_mcast_bcast_filter(pHddCtx);
1527#endif
1528
1529 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Flush Queues",__func__);
1530 //Clean up message queues of TX and MC thread
1531 vos_sched_flush_mc_mqs(vosSchedContext);
1532 vos_sched_flush_tx_mqs(vosSchedContext);
1533#ifdef FEATURE_WLAN_INTEGRATED_SOC
1534 vos_sched_flush_rx_mqs(vosSchedContext);
1535#endif
1536
1537 //Deinit all the TX and MC queues
1538 vos_sched_deinit_mqs(vosSchedContext);
1539
1540 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing VOS Close",__func__);
1541
1542 //Close VOSS
1543 vos_close(pVosContext);
1544
1545#ifdef ANI_BUS_TYPE_SDIO
1546 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing BAL Close",__func__);
1547 vosStatus = WLANBAL_Close(pVosContext);
1548 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1549 {
1550 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1551 "%s: Failed to close BAL",__func__);
1552 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1553 }
1554 //Get the Current SDIO Func
1555 sdio_func_dev_current = libra_getsdio_funcdev();
1556
1557 if(NULL != sdio_func_dev_current) {
1558 libra_detect_card_change();
1559 attempts = 0;
1560 do {
1561 msleep(100);
1562 //Get the SDIO func device
1563 sdio_func_dev_current = libra_getsdio_funcdev();
1564 if(NULL == sdio_func_dev_current) {
1565 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Card Removed Successfully",__func__);
1566 break;
1567 }
1568 else {
1569 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to Remove the Card: Trying Again",__func__);
1570 attempts++;
1571 }
1572 } while (attempts < LIBRA_CARD_REMOVE_DETECT_MAX_COUNT);
1573
1574 if(LIBRA_CARD_REMOVE_DETECT_MAX_COUNT == attempts) {
1575 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to Remove the Card: Fatal",__func__);
1576 goto err_fail;
1577 }
1578 }
1579#endif
1580
1581#ifdef TIMER_MANAGER
1582 vos_timer_exit();
1583#endif
1584
1585#ifdef MEMORY_DEBUG
1586 vos_mem_clean();
1587#endif
1588#ifdef ANI_BUS_TYPE_SDIO
1589 //Reinitialize the variable
1590 attempts = 0;
1591#endif
1592
1593 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Powering Up chip Again",__func__);
1594 //Power Up Libra WLAN card first if not already powered up
1595 vosStatus = vos_chipPowerUp(NULL,NULL,NULL);
1596 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1597 {
1598 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
1599 "exiting", __func__);
1600 goto err_pwr_fail;
1601 }
1602
1603#ifdef ANI_BUS_TYPE_SDIO
1604 // Trigger card detect
1605 libra_detect_card_change();
1606
1607 //Reinitialize the variable
1608 attempts = 0;
1609
1610 do {
1611 msleep(500);
1612
1613 //Get the SDIO func device
1614 sdio_func_dev_new = libra_getsdio_funcdev();
1615 if(sdio_func_dev_new != NULL)
1616 {
1617 //Not needed but in case it causes probs then put a loop and set for each adapter
1618 //SET_NETDEV_DEV(pAdapter->dev, &sdio_func_dev_new->dev);
1619 libra_sdio_setprivdata (sdio_func_dev_new, pHddCtx);
1620 atomic_set(&pHddCtx->sdio_claim_count, 0);
1621 pHddCtx->parent_dev = &sdio_func_dev_new->dev;
1622 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1623 "%s: Card Detected Successfully %p",__func__,
1624 sdio_func_dev_new);
1625 break;
1626 }
1627 else
1628 {
1629 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1630 "%s: Failed to detect card change %p",__func__,
1631 sdio_func_dev_new);
1632 attempts++;
1633 }
1634 }while (attempts < LIBRA_CARD_INSERT_DETECT_MAX_COUNT);
1635
1636 if(LIBRA_CARD_INSERT_DETECT_MAX_COUNT == attempts){
1637 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN fail to detect in reset, "
1638 "exiting", __func__);
1639 goto err_fail;
1640 }
1641 //Get the SDIO func device
1642 sdio_func_dev_new = libra_getsdio_funcdev();
1643 if(sdio_func_dev_new != NULL)
1644 {
1645 sd_claim_host(sdio_func_dev_new);
1646 /* Enable IRQ capabilities in host controller */
1647 libra_disable_sdio_irq_capability(sdio_func_dev_new, 0);
1648 libra_enable_sdio_irq(sdio_func_dev_new, 1);
1649 sd_release_host(sdio_func_dev_new);
1650 }
1651 else
1652 {
1653 /* Our card got removed before LOGP. */
1654 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
1655 goto err_fail;
1656 }
1657
1658 vosStatus = WLANBAL_Open(pVosContext);
1659 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1660 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1661 {
1662 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1663 "%s: Failed to open BAL",__func__);
1664 goto err_fail;
1665 }
1666
1667 vosStatus = WLANSAL_Start(pVosContext);
1668 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1669 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1670 {
1671 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to start SAL",__func__);
1672 goto err_balclose;
1673 }
1674
1675 /* Chip is reset so allow Lower MAC to start accessing WLAN registers. Note HDD is still blocked */
1676 vos_set_logp_in_progress(VOS_MODULE_ID_HDD, FALSE);
1677
1678 /* Start BAL */
1679 vosStatus = WLANBAL_Start(pVosContext);
1680
1681 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1682 {
1683 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1684 "%s: Failed to start BAL",__func__);
1685 goto err_salstop;
1686 }
1687#endif
1688 // Open VOSS
1689 vosStatus = vos_open( &pVosContext, 0);
1690
1691 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
1692 {
1693 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
1694#ifdef ANI_BUS_TYPE_SDIO
1695 goto err_balstop;
1696#else
1697 goto err_pwr_fail;
1698#endif
1699 }
1700
1701 /* Save the hal context in Adapter */
1702 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
1703
1704 if ( NULL == pHddCtx->hHal )
1705 {
1706 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
1707 goto err_vosclose;
1708 }
1709 // Set the SME configuration parameters...
1710 vosStatus = hdd_set_sme_config(pHddCtx);
1711
1712 if ( VOS_STATUS_SUCCESS != vosStatus )
1713 {
1714 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
1715 goto err_vosclose;
1716 }
1717
1718 //Initialize the WMM module
1719 vosStatus = hdd_wmm_init(pHddCtx);
1720 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
1721 {
1722 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __FUNCTION__);
1723 goto err_vosclose;
1724 }
1725
1726 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
1727 Note: Firmware image will be read and downloaded inside vos_start API */
1728 vosStatus = vos_start( pVosContext );
1729 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1730 {
1731 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
1732 goto err_vosclose;
1733 }
1734
1735 vosStatus = hdd_post_voss_start_config( pHddCtx );
1736 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1737 {
1738 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
1739 __func__);
1740 goto err_vosstop;
1741 }
1742
1743 /* Restart all adapters */
1744 hdd_start_all_adapters(pHddCtx);
1745 pHddCtx->isLogpInProgress = FALSE;
1746 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
1747#ifdef CONFIG_HAS_EARLYSUSPEND
1748 hdd_register_mcast_bcast_filter(pHddCtx);
1749#endif
1750
1751 // Allow the phone to go to sleep
1752 hdd_allow_suspend();
1753
1754 goto success;
1755
1756err_vosstop:
1757 vos_stop(pVosContext);
1758
1759err_vosclose:
1760 vos_close(pVosContext );
1761 vos_sched_close(pVosContext);
1762
1763#ifdef ANI_BUS_TYPE_SDIO
1764err_balstop:
1765#ifndef ANI_MANF_DIAG
1766 wlan_hdd_enable_deepsleep(pVosContext);
1767#endif
1768 WLANBAL_Stop(pVosContext);
1769 WLANBAL_SuspendChip(pVosContext);
1770
1771err_salstop:
1772 WLANSAL_Stop(pVosContext);
1773
1774err_balclose:
1775 WLANBAL_Close(pVosContext);
1776
1777err_fail:
1778 //Assert Deep sleep signal now to put Libra HW in lowest power state
1779 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
1780
1781 //Vote off any PMIC voltage supplies
1782 vos_chipPowerDown(NULL, NULL, NULL);
1783#endif
1784
1785err_pwr_fail:
1786 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
1787
1788 // Allow the phone to go to sleep
1789 hdd_allow_suspend();
1790
1791#ifdef CONFIG_HAS_EARLYSUSPEND
1792 // unregister suspend/resume callbacks
1793 if(pHddCtx->cfg_ini->nEnableSuspend)
1794 unregister_wlan_suspend();
1795#endif
1796
1797 // Unregister the Net Device Notifier
1798 unregister_netdevice_notifier(&hdd_netdev_notifier);
1799
1800 //Clean up HDD Nlink Service
1801 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1802 nl_srv_exit();
1803
1804 hdd_close_all_adapters(pHddCtx);
1805 //Free up dynamically allocated members inside HDD Adapter
1806 kfree(pHddCtx->cfg_ini);
1807 pHddCtx->cfg_ini= NULL;
1808
1809#ifdef CONFIG_CFG80211
1810 wiphy_unregister(pHddCtx->wiphy);
1811 wiphy_free(pHddCtx->wiphy);
1812#else
1813 vos_mem_free(pHddCtx);
1814#endif
1815
1816#ifdef ANI_BUS_TYPE_SDIO
1817 WLANSAL_Close(pVosContext);
1818#endif
1819 vos_preClose(&pVosContext);
1820
1821#ifdef MEMORY_DEBUG
1822 vos_mem_exit();
1823#endif
1824
1825 return -1;
1826
1827success:
1828 //Trigger replay of BTC events
1829 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1830 return VOS_STATUS_SUCCESS;
1831
1832}
1833
1834
1835
1836VOS_STATUS hdd_wlan_reset_initialization(void)
1837{
1838#ifdef ANI_BUS_TYPE_SDIO
1839 struct sdio_func *sdio_func_dev = NULL;
1840 v_U8_t regValue = 0;
1841 int err_ret = 0;
1842#endif
1843 v_CONTEXT_t pVosContext = NULL;
1844
1845 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1846
1847 //Get the global VOSS context.
1848 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1849 if(!pVosContext)
1850 {
1851 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1852 return VOS_STATUS_E_FAILURE;
1853 }
1854
1855 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__);
1856
1857 // Prevent the phone from going to sleep
1858 hdd_prevent_suspend();
1859
1860#ifdef ANI_BUS_TYPE_SDIO
1861 /* Clear pending interrupt and disable Interrupts. Use only CMD52 */
1862 VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
1863 "%s LOGP in progress. Disabling Interrupt", __func__);
1864
1865 sdio_func_dev = libra_getsdio_funcdev();
1866
1867 if(sdio_func_dev == NULL)
1868 {
1869 /* Our card got removed before LOGP. Continue with reset anyways */
1870 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
1871 return VOS_STATUS_SUCCESS;
1872 }
1873
1874 sd_claim_host(sdio_func_dev);
1875
1876 regValue = 0;
1877 libra_sdiocmd52(sdio_func_dev, QWLAN_SIF_SIF_INT_EN_REG,
1878 &regValue, 1, &err_ret);
1879
1880 VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
1881 "%s LOGP Cleared SIF_SIF_INT_EN_REG status:%d", __func__,err_ret);
1882
1883 regValue = 0;
1884 libra_sdiocmd52(sdio_func_dev, QWLAN_SIF_BAR4_INT_PEND_REG,
1885 &regValue, 1, &err_ret);
1886
1887 VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
1888 "%s LOGP Cleared SIF_BAR4_INT_PEND_REG status :%d", __func__,err_ret);
1889
1890 regValue = 0;
1891 libra_sdiocmd52(sdio_func_dev, QWLAN_SIF_BAR4_INT_ENABLE_REG,
1892 &regValue, 1, &err_ret);
1893
1894 VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
1895 "%s LOGP Cleared SIF_BAR4_INT_ENABLE_REG: Status:%d", __func__,err_ret);
1896
1897 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing Suspend Chip",__func__);
1898
1899 //Put the chip is standby before asserting deep sleep
1900 WLANBAL_SuspendChip_NoLock( pVosContext );
1901
1902 sd_release_host(sdio_func_dev);
1903#endif
1904
1905 return VOS_STATUS_SUCCESS;
1906}
1907
1908
1909void register_wlan_suspend(void)
1910{
1911 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Register WLAN suspend/resume "
1912 "callbacks",__func__);
1913 wlan_early_suspend.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING;
1914 wlan_early_suspend.suspend = hdd_suspend_wlan;
1915 wlan_early_suspend.resume = hdd_resume_wlan;
1916 register_early_suspend(&wlan_early_suspend);
1917}
1918
1919void unregister_wlan_suspend(void)
1920{
1921 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Unregister WLAN suspend/resume "
1922 "callbacks",__func__);
1923 unregister_early_suspend(&wlan_early_suspend);
1924}
1925#endif
1926
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001927static void hdd_ssr_timer_init(void)
1928{
1929 init_timer(&ssr_timer);
1930}
1931static void hdd_ssr_timer_del(void)
1932{
1933 del_timer(&ssr_timer);
1934 ssr_timer_started = false;
1935}
1936static void hdd_ssr_timer_cb(unsigned long data)
1937{
1938 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD SSR timer expired", __func__);
1939 VOS_BUG(0);
1940}
1941static void hdd_ssr_timer_start(int msec)
1942{
1943 if(ssr_timer_started)
1944 {
1945 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: trying to start SSR timer when it's running"
1946 ,__func__);
1947 }
1948 ssr_timer.expires = jiffies + msecs_to_jiffies(msec);
1949 ssr_timer.function = hdd_ssr_timer_cb;
1950 add_timer(&ssr_timer);
1951 ssr_timer_started = true;
1952}
Jeff Johnson295189b2012-06-20 16:38:30 -07001953/* the HDD interface to WLAN driver shutdown,
1954 * the primary shutdown function in SSR
1955 */
1956VOS_STATUS hdd_wlan_shutdown(void)
1957{
1958 VOS_STATUS vosStatus;
1959 v_CONTEXT_t pVosContext = NULL;
1960 hdd_context_t *pHddCtx = NULL;
1961 pVosSchedContext vosSchedContext = NULL;
1962
1963 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__);
1964
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001965 /* if re-init never happens, then do SSR1 */
1966 hdd_ssr_timer_init();
1967 hdd_ssr_timer_start(HDD_SSR_BRING_UP_TIME);
1968
Jeff Johnson295189b2012-06-20 16:38:30 -07001969 /* Get the global VOSS context. */
1970 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1971 if(!pVosContext) {
1972 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1973 return VOS_STATUS_E_FAILURE;
1974 }
1975 /* Get the HDD context. */
1976 pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1977 if(!pHddCtx) {
1978 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1979 return VOS_STATUS_E_FAILURE;
1980 }
1981 hdd_reset_all_adapters(pHddCtx);
1982#ifdef CONFIG_HAS_EARLYSUSPEND
1983 /* unregister suspend/resume callbacks */
1984 if(pHddCtx->cfg_ini->nEnableSuspend)
1985 {
1986 unregister_wlan_suspend();
1987 }
1988#endif
1989 /* DeRegister with platform driver as client for Suspend/Resume */
1990 vosStatus = hddDeregisterPmOps(pHddCtx);
1991 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1992 {
1993 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
1994 }
1995
1996 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
1997 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1998 {
1999 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
2000 }
2001
2002 /* Disable IMPS/BMPS as we do not want the device to enter any power
2003 * save mode on its own during reset sequence
2004 */
2005 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2006 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2007 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
2008
2009 vosSchedContext = get_vos_sched_ctxt();
2010
2011 /* Wakeup all driver threads */
2012 if(TRUE == pHddCtx->isMcThreadSuspended){
2013 complete(&vosSchedContext->ResumeMcEvent);
2014 pHddCtx->isMcThreadSuspended= FALSE;
2015 }
2016 if(TRUE == pHddCtx->isTxThreadSuspended){
2017 complete(&vosSchedContext->ResumeTxEvent);
2018 pHddCtx->isTxThreadSuspended= FALSE;
2019 }
2020 if(TRUE == pHddCtx->isRxThreadSuspended){
2021 complete(&vosSchedContext->ResumeRxEvent);
2022 pHddCtx->isRxThreadSuspended= FALSE;
2023 }
2024 /* Reset the Suspend Variable */
2025 pHddCtx->isWlanSuspended = FALSE;
2026
2027 /* Stop all the threads; we do not want any messages to be a processed,
2028 * any more and the best way to ensure that is to terminate the threads
2029 * gracefully.
2030 */
2031 /* Wait for MC to exit */
2032 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
2033 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
2034 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
2035 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
2036 wait_for_completion_interruptible(&vosSchedContext->McShutdown);
2037
2038 /* Wait for TX to exit */
2039 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
2040 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
2041 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
2042 wake_up_interruptible(&vosSchedContext->txWaitQueue);
2043 wait_for_completion_interruptible(&vosSchedContext->TxShutdown);
2044
2045 /* Wait for RX to exit */
2046 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
2047 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
2048 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
2049 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
2050 wait_for_completion_interruptible(&vosSchedContext->RxShutdown);
2051
2052#ifdef WLAN_BTAMP_FEATURE
2053 vosStatus = WLANBAP_Stop(pVosContext);
2054 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2055 {
2056 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2057 "%s: Failed to stop BAP",__func__);
2058 }
2059#endif //WLAN_BTAMP_FEATURE
2060 vosStatus = vos_wda_shutdown(pVosContext);
2061 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
2062
2063 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
2064 /* Stop SME - Cannot invoke vos_stop as vos_stop relies
2065 * on threads being running to process the SYS Stop
2066 */
2067 vosStatus = sme_Stop(pHddCtx->hHal, TRUE);
2068 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
2069
2070 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
2071 /* Stop MAC (PE and HAL) */
2072 vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
2073 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
2074
2075 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
2076 /* Stop TL */
2077 vosStatus = WLANTL_Stop(pVosContext);
2078 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
2079
2080#ifdef CONFIG_HAS_EARLYSUSPEND
2081 hdd_unregister_mcast_bcast_filter(pHddCtx);
2082#endif
2083 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__);
2084 /* Clean up message queues of TX and MC thread */
2085 vos_sched_flush_mc_mqs(vosSchedContext);
2086 vos_sched_flush_tx_mqs(vosSchedContext);
2087 vos_sched_flush_rx_mqs(vosSchedContext);
2088
2089 /* Deinit all the TX and MC queues */
2090 vos_sched_deinit_mqs(vosSchedContext);
2091 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__);
2092
2093 /* shutdown VOSS */
2094 vos_shutdown(pVosContext);
2095 if (free_riva_power_on_lock("wlan"))
2096 {
2097 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
2098 __func__);
2099 }
2100 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete"
2101 ,__func__);
2102 return VOS_STATUS_SUCCESS;
2103}
2104
2105
2106
2107/* the HDD interface to WLAN driver re-init.
2108 * This is called to initialize/start WLAN driver after a shutdown.
2109 */
2110VOS_STATUS hdd_wlan_re_init(void)
2111{
2112 VOS_STATUS vosStatus;
2113 v_CONTEXT_t pVosContext = NULL;
2114 hdd_context_t *pHddCtx = NULL;
2115 eHalStatus halStatus;
2116#ifdef WLAN_BTAMP_FEATURE
2117 hdd_config_t *pConfig = NULL;
2118 WLANBAP_ConfigType btAmpConfig;
2119#endif
2120
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07002121 hdd_ssr_timer_del();
Jeff Johnson295189b2012-06-20 16:38:30 -07002122 hdd_prevent_suspend();
2123 /* Re-open VOSS, it is a re-open b'se control transport was never closed. */
2124 vosStatus = vos_open(&pVosContext, 0);
2125 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2126 {
2127 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
2128 goto err_re_init;
2129 }
2130
2131 /* Get the HDD context. */
2132 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
2133 if(!pHddCtx)
2134 {
2135 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
2136 goto err_vosclose;
2137 }
2138
2139 /* Save the hal context in Adapter */
2140 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
2141 if ( NULL == pHddCtx->hHal )
2142 {
2143 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
2144 goto err_vosclose;
2145 }
2146
2147 /* Set the SME configuration parameters. */
2148 vosStatus = hdd_set_sme_config(pHddCtx);
2149 if ( VOS_STATUS_SUCCESS != vosStatus )
2150 {
2151 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
2152 goto err_vosclose;
2153 }
2154
2155 /* Initialize the WMM module */
2156 vosStatus = hdd_wmm_init(pHddCtx);
2157 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
2158 {
2159 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __FUNCTION__);
2160 goto err_vosclose;
2161 }
2162
2163 vosStatus = vos_preStart( pHddCtx->pvosContext );
2164 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2165 {
2166 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
2167 goto err_vosclose;
2168 }
2169
2170 /* In the integrated architecture we update the configuration from
2171 the INI file and from NV before vOSS has been started so that
2172 the final contents are available to send down to the cCPU */
2173 /* Apply the cfg.ini to cfg.dat */
2174 if (FALSE == hdd_update_config_dat(pHddCtx))
2175 {
2176 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
2177 goto err_vosclose;
2178 }
2179
2180 /* Set the MAC Address, currently this is used by HAL to add self sta.
2181 * Remove this once self sta is added as part of session open. */
2182 halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID,
2183 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
2184 sizeof(pHddCtx->cfg_ini->intfMacAddr[0]));
2185 if (!HAL_STATUS_SUCCESS(halStatus))
2186 {
2187 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
2188 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus);
2189 goto err_vosclose;
2190 }
2191
2192 /* Start VOSS which starts up the SME/MAC/HAL modules and everything else
2193 Note: Firmware image will be read and downloaded inside vos_start API */
2194 vosStatus = vos_start( pVosContext );
2195 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2196 {
2197 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
2198 goto err_vosclose;
2199 }
2200
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07002201 /* Exchange capability info between Host and FW and also get versioning info from FW */
2202 hdd_exchange_version_and_caps(pHddCtx);
2203
Jeff Johnson295189b2012-06-20 16:38:30 -07002204 vosStatus = hdd_post_voss_start_config( pHddCtx );
2205 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2206 {
2207 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
2208 __func__);
2209 goto err_vosstop;
2210 }
2211
2212#ifdef WLAN_BTAMP_FEATURE
2213 vosStatus = WLANBAP_Open(pVosContext);
2214 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
2215 {
2216 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2217 "%s: Failed to open BAP",__func__);
2218 goto err_vosstop;
2219 }
2220 vosStatus = BSL_Init(pVosContext);
2221 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
2222 {
2223 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2224 "%s: Failed to Init BSL",__func__);
2225 goto err_bap_close;
2226 }
2227 vosStatus = WLANBAP_Start(pVosContext);
2228 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2229 {
2230 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2231 "%s: Failed to start TL",__func__);
2232 goto err_bap_close;
2233 }
2234 pConfig = pHddCtx->cfg_ini;
2235 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
2236 vosStatus = WLANBAP_SetConfig(&btAmpConfig);
2237#endif //WLAN_BTAMP_FEATURE
2238
2239 /* Restart all adapters */
2240 hdd_start_all_adapters(pHddCtx);
2241 pHddCtx->isLogpInProgress = FALSE;
2242 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
2243#ifdef CONFIG_HAS_EARLYSUSPEND
2244 hdd_register_mcast_bcast_filter(pHddCtx);
2245#endif
2246
2247 /* Register with platform driver as client for Suspend/Resume */
2248 vosStatus = hddRegisterPmOps(pHddCtx);
2249 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2250 {
2251 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
2252 goto err_bap_stop;
2253 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002254#ifdef CONFIG_HAS_EARLYSUSPEND
Jeff Johnson295189b2012-06-20 16:38:30 -07002255 // Register suspend/resume callbacks
2256 if(pHddCtx->cfg_ini->nEnableSuspend)
2257 {
2258 register_wlan_suspend();
2259 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002260#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002261 /* Allow the phone to go to sleep */
2262 hdd_allow_suspend();
2263 /* register for riva power on lock */
2264 if (req_riva_power_on_lock("wlan"))
2265 {
2266 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
2267 __func__);
2268 goto err_unregister_pmops;
2269 }
2270 goto success;
2271
2272err_unregister_pmops:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002273#ifdef CONFIG_HAS_EARLYSUSPEND
2274 /* unregister suspend/resume callbacks */
2275 if (pHddCtx->cfg_ini->nEnableSuspend)
2276 unregister_wlan_suspend();
2277#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002278 hddDeregisterPmOps(pHddCtx);
2279
2280err_bap_stop:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002281#ifdef CONFIG_HAS_EARLYSUSPEND
2282 hdd_unregister_mcast_bcast_filter(pHddCtx);
2283#endif
2284 hdd_close_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002285#ifdef WLAN_BTAMP_FEATURE
Jeff Johnson32d95a32012-09-10 13:15:23 -07002286 WLANBAP_Stop(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07002287#endif
2288
2289#ifdef WLAN_BTAMP_FEATURE
2290err_bap_close:
2291 WLANBAP_Close(pVosContext);
2292#endif
2293
2294err_vosstop:
2295 vos_stop(pVosContext);
2296
2297err_vosclose:
2298 vos_close(pVosContext);
2299 vos_sched_close(pVosContext);
2300 if (pHddCtx)
2301 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002302 /* Unregister the Net Device Notifier */
2303 unregister_netdevice_notifier(&hdd_netdev_notifier);
2304 /* Clean up HDD Nlink Service */
2305 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
2306 nl_srv_exit();
Jeff Johnson295189b2012-06-20 16:38:30 -07002307 /* Free up dynamically allocated members inside HDD Adapter */
2308 kfree(pHddCtx->cfg_ini);
2309 pHddCtx->cfg_ini= NULL;
2310
2311#ifdef CONFIG_CFG80211
2312 wiphy_unregister(pHddCtx->wiphy);
2313 wiphy_free(pHddCtx->wiphy);
2314#else
2315 vos_mem_free(pHddCtx);
2316#endif
2317 }
2318 vos_preClose(&pVosContext);
2319
2320#ifdef MEMORY_DEBUG
2321 vos_mem_exit();
2322#endif
2323
2324err_re_init:
2325 /* Allow the phone to go to sleep */
2326 hdd_allow_suspend();
2327 return -1;
2328
2329success:
2330 /* Trigger replay of BTC events */
2331 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
2332 return VOS_STATUS_SUCCESS;
2333}