blob: 95a0ad91c2ce343ea25439524c256a167e67065b [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/******************************************************************************
43*
44* Name: pmc.c
45*
Jeff Johnsone7245742012-09-05 17:12:55 -070046* Description:
Jeff Johnson295189b2012-06-20 16:38:30 -070047 Power Management Control (PMC) processing routines.
48*
49* Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
50* Qualcomm Confidential and Proprietary.
51*
52*
53******************************************************************************/
54
55#include "palTypes.h"
56#include "aniGlobal.h"
57#include "csrLinkList.h"
58#include "csrApi.h"
59#include "smeInside.h"
60#include "sme_Api.h"
61#include "smsDebug.h"
62#include "pmc.h"
Mohit Khanna349bc392012-09-11 17:24:52 -070063#include "wlan_qct_wda.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070064#include "wlan_ps_wow_diag.h"
65#include <vos_power.h>
66#include "csrInsideApi.h"
67
68static void pmcProcessDeferredMsg( tpAniSirGlobal pMac );
69
70/******************************************************************************
71*
72* Name: pmcEnterLowPowerState
73*
74* Description:
75* Have the device enter Low Power State.
76*
77* Parameters:
78* hHal - HAL handle for device
79*
80* Returns:
81* eHAL_STATUS_SUCCESS - changing state successful
82* eHAL_STATUS_FAILURE - changing state not successful
83*
84******************************************************************************/
85eHalStatus pmcEnterLowPowerState (tHalHandle hHal)
86{
87 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
88
89 smsLog(pMac, LOG2, FL("Entering pmcEnterLowPowerState\n"));
90
91 /* If already in Low Power State, just return. */
92 if (pMac->pmc.pmcState == LOW_POWER)
93 return eHAL_STATUS_SUCCESS;
94
95 /* Cancel any running timers. */
96 if (palTimerStop(pMac->hHdd, pMac->pmc.hImpsTimer) != eHAL_STATUS_SUCCESS)
97 {
98 smsLog(pMac, LOGE, FL("Cannot cancel IMPS timer\n"));
99 return eHAL_STATUS_FAILURE;
100 }
101
102 pmcStopTrafficTimer(hHal);
103
104 if (palTimerStop(pMac->hHdd, pMac->pmc.hExitPowerSaveTimer) != eHAL_STATUS_SUCCESS)
105 {
106 smsLog(pMac, LOGE, FL("Cannot cancel exit power save mode timer\n"));
107 return eHAL_STATUS_FAILURE;
108 }
109
110 /* Do all the callbacks. */
111 pmcDoCallbacks(hHal, eHAL_STATUS_FAILURE);
112
113 /* Change state. */
114 pMac->pmc.pmcState = LOW_POWER;
115
116 return eHAL_STATUS_SUCCESS;
117}
118
119
120/******************************************************************************
121*
122* Name: pmcExitLowPowerState
123*
124* Description:
125* Have the device exit the Low Power State.
126*
127* Parameters:
128* hHal - HAL handle for device
129*
130* Returns:
131* eHAL_STATUS_SUCCESS - changing state successful
132* eHAL_STATUS_FAILURE - changing state not successful
133*
134******************************************************************************/
135eHalStatus pmcExitLowPowerState (tHalHandle hHal)
136{
137 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
138
139 smsLog(pMac, LOG2, FL("Entering pmcExitLowPowerState\n"));
140
141 /* Must be in Low Power State if we are going to exit that state. */
142 if (pMac->pmc.pmcState != LOW_POWER)
143 {
144 smsLog(pMac, LOGE, FL("Cannot exit Low Power State if not in that state\n"));
145 return eHAL_STATUS_FAILURE;
146 }
147
148 /* Both WLAN switches much be on to exit Low Power State. */
149 if ((pMac->pmc.hwWlanSwitchState == ePMC_SWITCH_OFF) || (pMac->pmc.swWlanSwitchState == ePMC_SWITCH_OFF))
150 return eHAL_STATUS_SUCCESS;
151
152 /* Change state. */
153 pMac->pmc.pmcState = FULL_POWER;
154 if(pmcShouldBmpsTimerRun(pMac))
155 {
156 if (pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod) != eHAL_STATUS_SUCCESS)
157 return eHAL_STATUS_FAILURE;
158 }
159
160 return eHAL_STATUS_SUCCESS;
161}
162
163
164/******************************************************************************
165*
166* Name: pmcEnterFullPowerState
167*
168* Description:
169* Have the device enter the Full Power State.
170*
171* Parameters:
172* hHal - HAL handle for device
173*
174* Returns:
175* eHAL_STATUS_SUCCESS - changing state successful
176* eHAL_STATUS_FAILURE - changing state not successful
177*
178******************************************************************************/
179eHalStatus pmcEnterFullPowerState (tHalHandle hHal)
180{
181 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
182
183 smsLog(pMac, LOG2, FL("Entering pmcEnterFullPowerState\n"));
184
185 /* Take action based on the current state. */
186 switch (pMac->pmc.pmcState)
187 {
188
189 /* Already in Full Power State. */
190 case FULL_POWER:
191 break;
192
193 /* Notify everyone that we are going to full power.
194 Change to Full Power State. */
195 case REQUEST_FULL_POWER:
196 case REQUEST_IMPS:
197 case REQUEST_BMPS:
198 case REQUEST_STANDBY:
199
200 /* Change state. */
201 pMac->pmc.pmcState = FULL_POWER;
202 pMac->pmc.requestFullPowerPending = FALSE;
203
204 if(pmcShouldBmpsTimerRun(pMac))
205 (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
206
207 pmcProcessDeferredMsg( pMac );
208 /* Do all the callbacks. */
209 pmcDoCallbacks(hHal, eHAL_STATUS_SUCCESS);
210
211 /* Update registerd modules that we are entering Full Power. This is
212 only way to inform modules if PMC exited a power save mode because
213 of error conditions or if som other module requested full power */
214 pmcDoDeviceStateUpdateCallbacks(hHal, FULL_POWER);
215 break;
216
217 /* Cannot go directly to Full Power State from these states. */
218 default:
219 smsLog(pMac, LOGE, FL("Trying to enter Full Power State from state %d\n"), pMac->pmc.pmcState);
220 PMC_ABORT;
221 return eHAL_STATUS_FAILURE;
222 }
223
Mohit Khanna23863762012-09-11 17:40:09 -0700224 smsLog(pMac, LOG1, "PMC: Enter full power done: Cancel XO Core ON vote\n");
Jeff Johnson295189b2012-06-20 16:38:30 -0700225 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
226 {
227 smsLog(pMac, LOGE, "Could not cancel XO Core ON vote. Not returning failure. "
228 "Power consumed will be high\n");
229 }
230
231 return eHAL_STATUS_SUCCESS;
232}
233
234
235/******************************************************************************
236*
237* Name: pmcEnterRequestFullPowerState
238*
239* Description:
240* Have the device enter the Request Full Power State.
241*
242* Parameters:
243* hHal - HAL handle for device
244* fullPowerReason - Reason code for requesting full power
245*
246* Returns:
247* eHAL_STATUS_SUCCESS - changing state successful
248* eHAL_STATUS_FAILURE - changing state not successful
249*
250******************************************************************************/
251eHalStatus pmcEnterRequestFullPowerState (tHalHandle hHal, tRequestFullPowerReason fullPowerReason)
252{
253 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
254 vos_call_status_type callType;
255 VOS_STATUS status;
256
257 smsLog(pMac, LOG2, FL("Entering pmcEnterRequestFullPowerState\n"));
258
259 /* Take action based on the current state of the device. */
260 switch (pMac->pmc.pmcState)
261 {
262
263 /* Should not request full power if already there. */
264 case FULL_POWER:
265 smsLog(pMac, LOGE, FL("Requesting Full Power State when already there\n"));
266 return eHAL_STATUS_FAILURE;
267
268 /* Only power events can take device out of Low Power State. */
269 case LOW_POWER:
270 smsLog(pMac, LOGE, FL("Cannot request exit from Low Power State\n"));
271 return eHAL_STATUS_FAILURE;
272
273 /* Cannot go directly to Request Full Power state from these states.
274 Record that this is pending and take care of it later. */
275 case REQUEST_IMPS:
276 case REQUEST_START_UAPSD:
277 case REQUEST_STOP_UAPSD:
278 case REQUEST_STANDBY:
279 case REQUEST_BMPS:
280 case REQUEST_ENTER_WOWL:
281 case REQUEST_EXIT_WOWL:
282 smsLog(pMac, LOGW, FL("Request for full power is being buffered. "
283 "Current state is %d\n"), pMac->pmc.pmcState);
284 //Ignore the new reason if request for full power is already pending
285 if( !pMac->pmc.requestFullPowerPending )
286 {
287 pMac->pmc.requestFullPowerPending = TRUE;
288 pMac->pmc.requestFullPowerReason = fullPowerReason;
289 }
290 return eHAL_STATUS_SUCCESS;
291
292 /* Tell MAC to have device enter full power mode. */
293 case IMPS:
294 if ( pMac->pmc.rfSuppliesVotedOff )
295 {
296 status = vos_chipVoteOnRFSupply(&callType, NULL, NULL);
297 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
298
299 status = vos_chipVoteOnXOBuffer(&callType, NULL, NULL);
300 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
301
302 pMac->pmc.rfSuppliesVotedOff = FALSE;
303 }
304
305 if (pmcIssueCommand( pMac, eSmeCommandExitImps, NULL, 0, FALSE ) != eHAL_STATUS_SUCCESS)
306 {
307 return eHAL_STATUS_FAILURE;
308 }
309 return eHAL_STATUS_SUCCESS;
310
311 /* Tell MAC to have device enter full power mode. */
312 case BMPS:
313 {
314 tExitBmpsInfo exitBmpsInfo;
315 exitBmpsInfo.exitBmpsReason = fullPowerReason;
316
317 if (pmcIssueCommand(hHal, eSmeCommandExitBmps, &exitBmpsInfo, sizeof(tExitBmpsInfo), FALSE)
318 != eHAL_STATUS_SUCCESS)
319 {
320 return eHAL_STATUS_FAILURE;
321 }
322 return eHAL_STATUS_SUCCESS;
323 }
324 /* Already in Request Full Power State. */
325 case REQUEST_FULL_POWER:
326 return eHAL_STATUS_SUCCESS;
327
328 /* Tell MAC to have device enter full power mode. */
329 case STANDBY:
330 if ( pMac->pmc.rfSuppliesVotedOff )
331 {
332 status = vos_chipVoteOnXOBuffer(&callType, NULL, NULL);
333 if(VOS_STATUS_SUCCESS != status)
334 {
335 return eHAL_STATUS_FAILURE;
336 }
337 status = vos_chipVoteOnRFSupply(&callType, NULL, NULL);
338 if(VOS_STATUS_SUCCESS != status)
339 {
340 return eHAL_STATUS_FAILURE;
341 }
342
343 pMac->pmc.rfSuppliesVotedOff = FALSE;
344 }
345
346 if (pmcIssueCommand(hHal, eSmeCommandExitImps, NULL, 0, FALSE) !=
347 eHAL_STATUS_SUCCESS)
348 {
349 smsLog(pMac, LOGE, "PMC: failure to send message "
350 "eWNI_PMC_EXIT_IMPS_REQ\n");
351 return eHAL_STATUS_FAILURE;
352 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700353
Jeff Johnson295189b2012-06-20 16:38:30 -0700354 return eHAL_STATUS_SUCCESS;
355
356 /* Tell MAC to have device exit UAPSD mode first */
357 case UAPSD:
358 //Need to save the reason code here in case later on we need to exit BMPS as well
359 if (pmcIssueCommand(hHal, eSmeCommandExitUapsd, &fullPowerReason, sizeof(tRequestFullPowerReason), FALSE) !=
360 eHAL_STATUS_SUCCESS)
361 {
362 smsLog(pMac, LOGE, "PMC: failure to send message "
363 "eWNI_PMC_EXIT_UAPSD_REQ\n");
364 return eHAL_STATUS_FAILURE;
365 }
366 return eHAL_STATUS_SUCCESS;
367
368 /* Tell MAC to have device exit WOWL mode first */
369 case WOWL:
370 if (pmcIssueCommand(hHal, eSmeCommandExitWowl, &fullPowerReason, sizeof(tRequestFullPowerReason), FALSE) !=
371 eHAL_STATUS_SUCCESS)
372 {
373 smsLog(pMac, LOGP, "PMC: failure to send message "
374 "eWNI_PMC_EXIT_WOWL_REQ\n");
375 return eHAL_STATUS_FAILURE;
376 }
377 return eHAL_STATUS_SUCCESS;
378
379 /* Cannot go directly to Request Full Power State from these states. */
380 default:
381 smsLog(pMac, LOGE, FL("Trying to enter Request Full Power State from state %d\n"), pMac->pmc.pmcState);
382 PMC_ABORT;
383 return eHAL_STATUS_FAILURE;
384 }
385}
386
387
388/******************************************************************************
389*
390* Name: pmcEnterRequestImpsState
391*
392* Description:
393* Have the device enter the Request IMPS State.
394*
395* Parameters:
396* hHal - HAL handle for device
397*
398* Returns:
399* eHAL_STATUS_SUCCESS - changing state successful
400* eHAL_STATUS_FAILURE - changing state not successful
401*
402******************************************************************************/
403eHalStatus pmcEnterRequestImpsState (tHalHandle hHal)
404{
405 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
406
407 smsLog(pMac, LOG2, FL("Entering pmcEnterRequestImpsState\n"));
408
409 /* Can enter Request IMPS State only from Full Power State. */
410 if (pMac->pmc.pmcState != FULL_POWER)
411 {
412 smsLog(pMac, LOGE, FL("Trying to enter Request IMPS State from state %d\n"), pMac->pmc.pmcState);
413 return eHAL_STATUS_FAILURE;
414 }
415
416 /* Make sure traffic timer that triggers bmps entry is not running */
417 pmcStopTrafficTimer(hHal);
418
419 /* Tell MAC to have device enter IMPS mode. */
420 if (pmcIssueCommand(hHal, eSmeCommandEnterImps, NULL, 0, FALSE) != eHAL_STATUS_SUCCESS)
421 {
422 smsLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_IMPS_REQ\n");
423 pMac->pmc.pmcState = FULL_POWER;
424 if(pmcShouldBmpsTimerRun(pMac))
425 (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
426 return eHAL_STATUS_FAILURE;
427 }
428
Mohit Khanna23863762012-09-11 17:40:09 -0700429 smsLog(pMac, LOG2, FL("eWNI_PMC_ENTER_IMPS_REQ sent to PE\n"));
Jeff Johnson295189b2012-06-20 16:38:30 -0700430
431 return eHAL_STATUS_SUCCESS;
432}
433
434
435/******************************************************************************
436*
437* Name: pmcEnterImpsState
438*
439* Description:
440* Have the device enter the IMPS State.
441*
442* Parameters:
443* hHal - HAL handle for device
444*
445* Returns:
446* eHAL_STATUS_SUCCESS - changing state successful
447* eHAL_STATUS_FAILURE - changing state not successful
448*
449******************************************************************************/
450eHalStatus pmcEnterImpsState (tHalHandle hHal)
451{
452 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
453 vos_call_status_type callType;
454 VOS_STATUS status;
455 smsLog(pMac, LOG2, FL("Entering pmcEnterImpsState\n"));
456
457 /* Can enter IMPS State only from Request IMPS State. */
458 if (pMac->pmc.pmcState != REQUEST_IMPS)
459 {
460 smsLog(pMac, LOGE, FL("Trying to enter IMPS State from state %d\n"), pMac->pmc.pmcState);
461 return eHAL_STATUS_FAILURE;
462 }
463
464 /* Change state. */
465 pMac->pmc.pmcState = IMPS;
466
467 /* If we have a reqeust for full power pending then we have to go
468 directly into full power. */
469 if (pMac->pmc.requestFullPowerPending)
470 {
471
Jeff Johnson295189b2012-06-20 16:38:30 -0700472 /* Start exit IMPS sequence now. */
473 return pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason);
Jeff Johnson295189b2012-06-20 16:38:30 -0700474 }
475
476 /* Set timer to come out of IMPS.only if impsPeriod is non-Zero*/
477 if(0 != pMac->pmc.impsPeriod)
478 {
479 if (palTimerStart(pMac->hHdd, pMac->pmc.hImpsTimer, pMac->pmc.impsPeriod * 1000, FALSE) != eHAL_STATUS_SUCCESS)
480 {
481 smsLog(pMac, LOGE, FL("Cannot start IMPS timer\n"));
482 PMC_ABORT;
483 pmcEnterRequestFullPowerState(hHal, eSME_REASON_OTHER);
484 return eHAL_STATUS_FAILURE;
485 }
486 }
487
Jeff Johnsone7245742012-09-05 17:12:55 -0700488 //Vote off RF supplies. Note RF supllies are not voted off if there is a
Jeff Johnson295189b2012-06-20 16:38:30 -0700489 //pending request for full power already
490 status = vos_chipVoteOffRFSupply(&callType, NULL, NULL);
491 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
492
493 status = vos_chipVoteOffXOBuffer(&callType, NULL, NULL);
494 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
495
496 pMac->pmc.rfSuppliesVotedOff= TRUE;
497
498 return eHAL_STATUS_SUCCESS;
499}
500
501
502/******************************************************************************
503*
504* Name: pmcEnterRequestBmpsState
505*
506* Description:
507* Have the device enter the Request BMPS State.
508*
509* Parameters:
510* hHal - HAL handle for device
511*
512* Returns:
513* eHAL_STATUS_SUCCESS - changing state successful
514* eHAL_STATUS_FAILURE - changing state not successful
515*
516******************************************************************************/
517eHalStatus pmcEnterRequestBmpsState (tHalHandle hHal)
518{
519 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
Jeff Johnsone7245742012-09-05 17:12:55 -0700520
Jeff Johnson295189b2012-06-20 16:38:30 -0700521 smsLog(pMac, LOG2, FL("Entering pmcEnterRequestBmpsState\n"));
522
523 /* Can enter Request BMPS State only from Full Power State. */
524 if (pMac->pmc.pmcState != FULL_POWER)
525 {
526 smsLog(pMac, LOGE, FL("Trying to enter Request BMPS State from state %d\n"), pMac->pmc.pmcState);
527 return eHAL_STATUS_FAILURE;
528 }
529
530 /* Stop Traffic timer if running. Note: timer could have expired because of possible
531 race conditions. So no need to check for errors. Just make sure timer is not running */
532 pmcStopTrafficTimer(hHal);
533
534 /* Tell MAC to have device enter BMPS mode. */
535 if ( !pMac->pmc.bmpsRequestQueued )
536 {
537 pMac->pmc.bmpsRequestQueued = eANI_BOOLEAN_TRUE;
538 if(pmcIssueCommand(hHal, eSmeCommandEnterBmps, NULL, 0, FALSE) != eHAL_STATUS_SUCCESS)
539 {
540 smsLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_BMPS_REQ\n");
541 pMac->pmc.bmpsRequestQueued = eANI_BOOLEAN_FALSE;
542 pMac->pmc.pmcState = FULL_POWER;
543 if(pmcShouldBmpsTimerRun(pMac))
544 {
545 (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
546 }
547 return eHAL_STATUS_FAILURE;
548 }
549 }
550 else
551 {
552 smsLog(pMac, LOGE, "PMC: enter BMPS command already queued\n");
553 //restart the timer if needed
554 if(pmcShouldBmpsTimerRun(pMac))
555 {
556 (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
557 }
558 return eHAL_STATUS_SUCCESS;
559 }
560
561 smsLog(pMac, LOGW, FL("eWNI_PMC_ENTER_BMPS_REQ sent to PE\n"));
562
563 return eHAL_STATUS_SUCCESS;
564}
565
566
567/******************************************************************************
568*
569* Name: pmcEnterBmpsState
570*
571* Description:
572* Have the device enter the BMPS State.
573*
574* Parameters:
575* hHal - HAL handle for device
576*
577* Returns:
578* eHAL_STATUS_SUCCESS - changing state successful
579* eHAL_STATUS_FAILURE - changing state not successful
580*
581******************************************************************************/
582eHalStatus pmcEnterBmpsState (tHalHandle hHal)
583{
584 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
585
586 smsLog(pMac, LOG2, FL("Entering pmcEnterBmpsState\n"));
587
588 /* Can enter BMPS State only from 5 states. */
589 if (pMac->pmc.pmcState != REQUEST_BMPS &&
590 pMac->pmc.pmcState != REQUEST_START_UAPSD &&
591 pMac->pmc.pmcState != REQUEST_STOP_UAPSD &&
592 pMac->pmc.pmcState != REQUEST_ENTER_WOWL &&
593 pMac->pmc.pmcState != REQUEST_EXIT_WOWL)
594 {
595 smsLog(pMac, LOGE, FL("Trying to enter BMPS State from state %d\n"), pMac->pmc.pmcState);
596 return eHAL_STATUS_FAILURE;
597 }
598
599 /* Change state. */
600 pMac->pmc.pmcState = BMPS;
601
602 /* Update registerd modules that we are entering BMPS. This is
603 only way to inform modules if PMC entered BMPS power save mode
604 on its own because of traffic timer */
605 pmcDoDeviceStateUpdateCallbacks(hHal, BMPS);
606
607 /* If we have a reqeust for full power pending then we have to go directly into full power. */
608 if (pMac->pmc.requestFullPowerPending)
609 {
610
Jeff Johnson295189b2012-06-20 16:38:30 -0700611 /* Start exit BMPS sequence now. */
612 smsLog(pMac, LOGW, FL("Pending Full Power request found on entering BMPS mode. "
613 "Start exit BMPS exit sequence\n"));
614 //Note: Reason must have been set when requestFullPowerPending flag was set.
615 pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason);
616 return eHAL_STATUS_SUCCESS;
Jeff Johnson295189b2012-06-20 16:38:30 -0700617 }
618
619 /*This should never happen ideally. WOWL and UAPSD not supported at the same time */
620 if (pMac->pmc.wowlModeRequired && pMac->pmc.uapsdSessionRequired)
621 {
622 smsLog(pMac, LOGW, FL("Both UAPSD and WOWL is required on entering BMPS mode. "
623 "UAPSD will be prioritized over WOWL\n"));
624 }
625
626 /* Do we need Uapsd?*/
627 if (pMac->pmc.uapsdSessionRequired)
628 {
629 smsLog(pMac, LOGW, FL("UAPSD session is required on entering BMPS mode. "
630 "Start UAPSD entry sequence\n"));
631 pmcEnterRequestStartUapsdState(hHal);
632 return eHAL_STATUS_SUCCESS;
633 }
634
635 /* Do we need WOWL?*/
636 if (pMac->pmc.wowlModeRequired)
637 {
638 smsLog(pMac, LOGW, FL("WOWL is required on entering BMPS mode. "
639 "Start WOWL entry sequence\n"));
640 pmcRequestEnterWowlState(hHal, &(pMac->pmc.wowlEnterParams));
641 }
642
643 return eHAL_STATUS_SUCCESS;
644}
645
646
647/******************************************************************************
648*
649* Name: pmcPowerSaveCheck
650*
651* Description:
652* Check if device is allowed to enter a power save mode.
653*
654* Parameters:
655* hHal - HAL handle for device
656*
657* Returns:
658* TRUE - entry is allowed
659* FALSE - entry is not allowed at this time
660*
661******************************************************************************/
662tANI_BOOLEAN pmcPowerSaveCheck (tHalHandle hHal)
663{
664 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
665 tListElem *pEntry;
666 tpPowerSaveCheckEntry pPowerSaveCheckEntry;
667 tANI_BOOLEAN (*checkRoutine) (void *checkContext);
668 tANI_BOOLEAN bResult=FALSE;
669
670 smsLog(pMac, LOG2, FL("Entering pmcPowerSaveCheck\n"));
671
672 /* Call the routines in the power save check routine list. If any
673 return FALSE, then we cannot go into power save mode. */
674 pEntry = csrLLPeekHead(&pMac->pmc.powerSaveCheckList, FALSE);
675 while (pEntry != NULL)
676 {
677 pPowerSaveCheckEntry = GET_BASE_ADDR(pEntry, tPowerSaveCheckEntry, link);
678 checkRoutine = pPowerSaveCheckEntry->checkRoutine;
679
680 /* If the checkRoutine is NULL for a paricular entry, proceed with other entries
681 * in the list */
682 if (NULL != checkRoutine)
683 {
684 if (!checkRoutine(pPowerSaveCheckEntry->checkContext))
685 {
686 smsLog(pMac, LOGE, FL("pmcPowerSaveCheck fail!\n"));
Jeff Johnsone7245742012-09-05 17:12:55 -0700687 bResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700688 break;
689 }
690 else
691 {
692 bResult = TRUE;
693 }
694 }
695 pEntry = csrLLNext(&pMac->pmc.powerSaveCheckList, pEntry, FALSE);
696 }
697
698 return bResult;
699}
700
701
702/******************************************************************************
703*
704* Name: pmcSendPowerSaveConfigMessage
705*
706* Description:
707* Send a message to PE/MAC to configure the power saving modes.
708*
709* Parameters:
710* hHal - HAL handle for device
711*
712* Returns:
713* eHAL_STATUS_SUCCESS - message successfuly sent
714* eHAL_STATUS_FAILURE - error while sending message
715*
716******************************************************************************/
717eHalStatus pmcSendPowerSaveConfigMessage (tHalHandle hHal)
718{
719 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
720 tSirPowerSaveCfg powerSaveConfig;
721
722 smsLog(pMac, LOG2, FL("Entering pmcSendPowerSaveConfigMessage\n"));
Jeff Johnsone7245742012-09-05 17:12:55 -0700723
Jeff Johnson295189b2012-06-20 16:38:30 -0700724 palZeroMemory(pMac->hHdd, &(powerSaveConfig), sizeof(tSirPowerSaveCfg));
725
726 switch (pMac->pmc.bmpsConfig.forwardBeacons)
727 {
728 case ePMC_NO_BEACONS:
729 powerSaveConfig.beaconFwd = ePM_BEACON_FWD_NONE;
730 break;
731 case ePMC_BEACONS_WITH_TIM_SET:
732 powerSaveConfig.beaconFwd = ePM_BEACON_FWD_TIM;
733 break;
734 case ePMC_BEACONS_WITH_DTIM_SET:
735 powerSaveConfig.beaconFwd = ePM_BEACON_FWD_DTIM;
736 break;
737 case ePMC_NTH_BEACON:
738 powerSaveConfig.beaconFwd = ePM_BEACON_FWD_NTH;
739 powerSaveConfig.nthBeaconFwd = (tANI_U16)pMac->pmc.bmpsConfig.valueOfN;
740 break;
741 case ePMC_ALL_BEACONS:
742 powerSaveConfig.beaconFwd = ePM_BEACON_FWD_NTH;
743 powerSaveConfig.nthBeaconFwd = 1;
744 break;
745 }
746 powerSaveConfig.fEnablePwrSaveImmediately = pMac->pmc.bmpsConfig.setPmOnLastFrame;
747 powerSaveConfig.fPSPoll = pMac->pmc.bmpsConfig.usePsPoll;
Jeff Johnsone7245742012-09-05 17:12:55 -0700748 powerSaveConfig.fEnableBeaconEarlyTermination =
Jeff Johnson295189b2012-06-20 16:38:30 -0700749 pMac->pmc.bmpsConfig.enableBeaconEarlyTermination;
Jeff Johnsone7245742012-09-05 17:12:55 -0700750 powerSaveConfig.bcnEarlyTermWakeInterval =
Jeff Johnson295189b2012-06-20 16:38:30 -0700751 pMac->pmc.bmpsConfig.bcnEarlyTermWakeInterval;
752
Jeff Johnsone7245742012-09-05 17:12:55 -0700753 /* setcfg for listenInterval. Make sure CFG is updated because PE reads this
Jeff Johnson295189b2012-06-20 16:38:30 -0700754 from CFG at the time of assoc or reassoc */
Jeff Johnsone7245742012-09-05 17:12:55 -0700755 ccmCfgSetInt(pMac, WNI_CFG_LISTEN_INTERVAL, pMac->pmc.bmpsConfig.bmpsPeriod,
Jeff Johnson295189b2012-06-20 16:38:30 -0700756 NULL, eANI_BOOLEAN_FALSE);
757
758 if( pMac->pmc.pmcState == IMPS || pMac->pmc.pmcState == REQUEST_IMPS )
759 {
760 //Wake up the chip first
Jeff Johnsone7245742012-09-05 17:12:55 -0700761 eHalStatus status = pmcDeferMsg( pMac, eWNI_PMC_PWR_SAVE_CFG,
Jeff Johnson295189b2012-06-20 16:38:30 -0700762 &powerSaveConfig, sizeof(tSirPowerSaveCfg) );
763
764 if( eHAL_STATUS_PMC_PENDING == status )
765 {
766 return eHAL_STATUS_SUCCESS;
767 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700768 else
Jeff Johnson295189b2012-06-20 16:38:30 -0700769 {
770 //either fail or already in full power
771 if( !HAL_STATUS_SUCCESS( status ) )
772 {
773 return ( status );
774 }
775 //else let it through because it is in full power state
776 }
777 }
778 /* Send a message so that FW System config is also updated and is in sync with
779 the CFG.*/
Jeff Johnsone7245742012-09-05 17:12:55 -0700780 if (pmcSendMessage(hHal, eWNI_PMC_PWR_SAVE_CFG, &powerSaveConfig, sizeof(tSirPowerSaveCfg))
Jeff Johnson295189b2012-06-20 16:38:30 -0700781 != eHAL_STATUS_SUCCESS)
782 {
783 smsLog(pMac, LOGE, FL("Send of eWNI_PMC_PWR_SAVE_CFG to PE failed\n"));
784 return eHAL_STATUS_FAILURE;
785 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700786
Jeff Johnson295189b2012-06-20 16:38:30 -0700787 return eHAL_STATUS_SUCCESS;
788}
789
790
791/******************************************************************************
792*
793* Name: pmcSendMessage
794*
795* Description:
796* Send a message to PE/MAC.
797*
798* Parameters:
799* hHal - HAL handle for device
800* messageType - message type to send
801* pMessageData - pointer to message data
802* messageSize - Size of the message data
803*
804* Returns:
805* eHAL_STATUS_SUCCESS - message successfuly sent
806* eHAL_STATUS_FAILURE - error while sending message
807*
808******************************************************************************/
809eHalStatus pmcSendMessage (tpAniSirGlobal pMac, tANI_U16 messageType, void *pMessageData, tANI_U32 messageSize)
810{
811 tSirMbMsg *pMsg;
812
813 smsLog(pMac, LOG2, FL("Entering pmcSendMessage, message type %d\n"), messageType);
814
815 /* Allocate and fill in message. */
816 if (palAllocateMemory(pMac->hHdd, (void **)&pMsg, WNI_CFG_MB_HDR_LEN + messageSize) != eHAL_STATUS_SUCCESS)
817 {
818 smsLog(pMac, LOGE, FL("Cannot allocate memory for message\n"));
819 PMC_ABORT;
820 return eHAL_STATUS_FAILURE;
821 }
822 pMsg->type = messageType;
823 pMsg->msgLen = (tANI_U16) (WNI_CFG_MB_HDR_LEN + messageSize);
824 if (messageSize > 0)
825 {
826 if (palCopyMemory(pMac->hHdd, pMsg->data, pMessageData, messageSize) != eHAL_STATUS_SUCCESS)
827 {
828 smsLog(pMac, LOGE, FL("Cannot copy message data\n"));
829 PMC_ABORT;
830 return eHAL_STATUS_FAILURE;
831 }
832 }
833
834 /* Send message. */
835 if (palSendMBMessage(pMac->hHdd, pMsg) != eHAL_STATUS_SUCCESS)
836 {
837 smsLog(pMac, LOGE, FL("Cannot send message\n"));
838 PMC_ABORT;
839 return eHAL_STATUS_FAILURE;
840 }
841
842 return eHAL_STATUS_SUCCESS;
843}
844
845
846/******************************************************************************
847*
848* Name: pmcDoCallbacks
849*
850* Description:
851* Call the IMPS callback routine and the routines in the request full
852* power callback routine list.
853*
854* Parameters:
855* hHal - HAL handle for device
856* callbackStatus - status to pass to the callback routines
857*
858* Returns:
859* nothing
860*
861******************************************************************************/
862void pmcDoCallbacks (tHalHandle hHal, eHalStatus callbackStatus)
863{
864 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
865 tListElem *pEntry;
866 tpRequestFullPowerEntry pRequestFullPowerEntry;
867
868 smsLog(pMac, LOG2, FL("Entering pmcDoCallbacks\n"));
869
870 /* Call IMPS callback routine. */
871 if (pMac->pmc.impsCallbackRoutine != NULL)
872 {
873 pMac->pmc.impsCallbackRoutine(pMac->pmc.impsCallbackContext, callbackStatus);
874 pMac->pmc.impsCallbackRoutine = NULL;
875 }
876
877 /* Call the routines in the request full power callback routine list. */
878 while (NULL != (pEntry = csrLLRemoveHead(&pMac->pmc.requestFullPowerList, TRUE)))
879 {
880 pRequestFullPowerEntry = GET_BASE_ADDR(pEntry, tRequestFullPowerEntry, link);
881 if (pRequestFullPowerEntry->callbackRoutine)
882 pRequestFullPowerEntry->callbackRoutine(pRequestFullPowerEntry->callbackContext, callbackStatus);
883 if (palFreeMemory(pMac->hHdd, pRequestFullPowerEntry) != eHAL_STATUS_SUCCESS)
884 {
885 smsLog(pMac, LOGE, FL("Cannot free request full power routine list entry\n"));
886 PMC_ABORT;
887 }
888 }
889
890}
891
892
893/******************************************************************************
894*
895* Name: pmcStartTrafficTimer
896*
897* Description:
898* Start the timer used in Full Power State to measure traffic
899* levels and determine when to enter BMPS.
900*
901* Parameters:
902* hHal - HAL handle for device
903*
904* Returns:
905* eHAL_STATUS_SUCCESS - timer successfuly started
906* eHAL_STATUS_FAILURE - error while starting timer
907*
908******************************************************************************/
909eHalStatus pmcStartTrafficTimer (tHalHandle hHal, tANI_U32 expirationTime)
910{
911 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
912 VOS_STATUS vosStatus;
913
914 smsLog(pMac, LOG2, FL("Entering pmcStartTrafficTimer\n"));
915
916 vosStatus = vos_timer_start(&pMac->pmc.hTrafficTimer, expirationTime);
917 if ( !VOS_IS_STATUS_SUCCESS(vosStatus) )
918 {
919 if( VOS_STATUS_E_ALREADY == vosStatus )
920 {
921 //Consider this ok since the timer is already started.
922 smsLog(pMac, LOGW, FL(" traffic timer is already started\n"));
923 }
924 else
925 {
926 smsLog(pMac, LOGP, FL("Cannot start traffic timer\n"));
927 return eHAL_STATUS_FAILURE;
928 }
929 }
930
931 return eHAL_STATUS_SUCCESS;
932}
933
934
935/******************************************************************************
936*
937* Name: pmcStopTrafficTimer
938*
939* Description:
940* Cancels the timer (if running) used in Full Power State to measure traffic
941* levels and determine when to enter BMPS.
942*
943* Parameters:
944* hHal - HAL handle for device
945*
946*
947******************************************************************************/
948void pmcStopTrafficTimer (tHalHandle hHal)
949{
950 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
951 smsLog(pMac, LOG2, FL("Entering pmcStopTrafficTimer\n"));
952 vos_timer_stop(&pMac->pmc.hTrafficTimer);
953}
954
955
956/******************************************************************************
957*
958* Name: pmcImpsTimerExpired
959*
960* Description:
961* Called when IMPS timer expires.
962*
963* Parameters:
964* hHal - HAL handle for device
965*
966* Returns:
967* nothing
968*
969******************************************************************************/
970void pmcImpsTimerExpired (tHalHandle hHal)
971{
972 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
973
974 smsLog(pMac, LOG2, FL("Entering pmcImpsTimerExpired\n"));
975
976 /* If timer expires and we are in a state other than IMPS State then something is wrong. */
977 if (pMac->pmc.pmcState != IMPS)
978 {
979 smsLog(pMac, LOGE, FL("Got IMPS timer expiration in state %d\n"), pMac->pmc.pmcState);
980 PMC_ABORT;
981 return;
982 }
983
984 /* Start on the path of going back to full power. */
985 pmcEnterRequestFullPowerState(hHal, eSME_REASON_OTHER);
986}
987
988
989/******************************************************************************
990*
991* Name: pmcTrafficTimerExpired
992*
993* Description:
994* Called when traffic measurement timer expires.
995*
996* Parameters:
997* hHal - HAL handle for device
998*
999* Returns:
1000* nothing
1001*
1002******************************************************************************/
1003void pmcTrafficTimerExpired (tHalHandle hHal)
1004{
1005
1006 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1007 VOS_STATUS vosStatus;
1008
Mohit Khanna23863762012-09-11 17:40:09 -07001009 smsLog(pMac, LOG2, FL("BMPS Traffic timer expired"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001010
1011 /* If timer expires and we are in a state other than Full Power State then something is wrong. */
1012 if (pMac->pmc.pmcState != FULL_POWER)
1013 {
1014 smsLog(pMac, LOGE, FL("Got traffic timer expiration in state %d"), pMac->pmc.pmcState);
1015 return;
1016 }
1017
1018 /* Untill DHCP is not completed remain in power active */
1019 if(pMac->pmc.remainInPowerActiveTillDHCP)
1020 {
Mohit Khanna23863762012-09-11 17:40:09 -07001021 smsLog(pMac, LOG2, FL("BMPS Traffic Timer expired before DHCP completion ignore enter BMPS\n"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001022 pMac->pmc.remainInPowerActiveThreshold++;
1023 if( pMac->pmc.remainInPowerActiveThreshold >= DHCP_REMAIN_POWER_ACTIVE_THRESHOLD)
1024 {
1025 smsLog(pMac, LOGE, FL("Remain in power active DHCP threshold reached FALLBACK to enable enter BMPS\n"));
1026 /*FALLBACK: reset the flag to make BMPS entry possible*/
1027 pMac->pmc.remainInPowerActiveTillDHCP = FALSE;
1028 pMac->pmc.remainInPowerActiveThreshold = 0;
1029 }
1030 //Activate the Traffic Timer again for entering into BMPS
1031 vosStatus = vos_timer_start(&pMac->pmc.hTrafficTimer, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
1032 if ( !VOS_IS_STATUS_SUCCESS(vosStatus) && (VOS_STATUS_E_ALREADY != vosStatus) )
1033 {
1034 smsLog(pMac, LOGP, FL("Cannot re-start traffic timer\n"));
1035 }
1036 return;
1037 }
1038
1039 /* Clear remain in power active threshold */
1040 pMac->pmc.remainInPowerActiveThreshold = 0;
1041
1042 /* Check if the timer should be running */
1043 if (!pmcShouldBmpsTimerRun(pMac))
1044 {
1045 smsLog(pMac, LOGE, FL("BMPS timer should not be running"));
1046 return;
1047 }
1048
Jeff Johnsone7245742012-09-05 17:12:55 -07001049 if (pmcPowerSaveCheck(hHal))
Jeff Johnson295189b2012-06-20 16:38:30 -07001050 {
1051 smsLog(pMac, LOGW, FL("BMPS entry criteria satisfied. Requesting BMPS state"));
Jeff Johnsone7245742012-09-05 17:12:55 -07001052 (void)pmcEnterRequestBmpsState(hHal);
1053 }
1054 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001055 {
1056 /*Some module voted against Power Save. So timer should be restarted again to retry BMPS */
1057 smsLog(pMac, LOGE, FL("Power Save check failed. Retry BMPS again later"));
1058 //Since hTrafficTimer is a vos_timer now, we need to restart the timer here
1059 vosStatus = vos_timer_start(&pMac->pmc.hTrafficTimer, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
1060 if ( !VOS_IS_STATUS_SUCCESS(vosStatus) && (VOS_STATUS_E_ALREADY != vosStatus) )
1061 {
1062 smsLog(pMac, LOGP, FL("Cannot start traffic timer\n"));
1063 return;
1064 }
1065 }
1066}
1067
1068
1069/******************************************************************************
1070*
1071* Name: pmcExitPowerSaveTimerExpired
1072*
1073* Description:
1074* Called when timer used to schedule a deferred power save mode exit expires.
1075*
1076* Parameters:
1077* hHal - HAL handle for device
1078*
1079* Returns:
1080* nothing
1081*
1082******************************************************************************/
1083void pmcExitPowerSaveTimerExpired (tHalHandle hHal)
1084{
1085 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1086
1087 smsLog(pMac, LOG2, FL("Entering pmcExitPowerSaveTimerExpired\n"));
1088
1089 /* Make sure process of exiting power save mode might hasn't already been started due to another trigger. */
1090 if (pMac->pmc.requestFullPowerPending)
1091
1092 /* Start on the path of going back to full power. */
1093 pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason);
1094}
1095
1096/******************************************************************************
1097*
1098* Name: pmcDoBmpsCallbacks
1099*
1100* Description:
1101* Call the registered BMPS callback routines because device is unable to
1102* enter BMPS state
1103*
1104* Parameters:
1105* hHal - HAL handle for device
1106* callbackStatus - Success or Failure.
1107*
1108* Returns:
1109* nothing
1110*
1111******************************************************************************/
1112void pmcDoBmpsCallbacks (tHalHandle hHal, eHalStatus callbackStatus)
1113{
1114 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1115 tListElem *pEntry;
1116 tpRequestBmpsEntry pRequestBmpsEntry;
1117
1118 smsLog(pMac, LOG2, "PMC: entering pmcDoBmpsCallbacks\n");
1119
1120 /* Call the routines in the request BMPS callback routine list. */
1121 pEntry = csrLLRemoveHead(&pMac->pmc.requestBmpsList, FALSE);
1122 while (pEntry != NULL)
1123 {
1124 pRequestBmpsEntry = GET_BASE_ADDR(pEntry, tRequestBmpsEntry, link);
1125 if (pRequestBmpsEntry->callbackRoutine)
1126 pRequestBmpsEntry->callbackRoutine(pRequestBmpsEntry->callbackContext,
1127 callbackStatus);
1128 palFreeMemory(pMac->hHdd, pRequestBmpsEntry);
1129 pEntry = csrLLRemoveHead(&pMac->pmc.requestBmpsList, FALSE);
1130 }
1131}
1132
1133
1134
1135
1136/******************************************************************************
1137*
1138* Name: pmcDoStartUapsdCallbacks
1139*
1140* Description:
1141* Call the registered UAPSD callback routines because device is unable to
1142* start UAPSD state
1143*
1144* Parameters:
1145* hHal - HAL handle for device
Jeff Johnsone7245742012-09-05 17:12:55 -07001146* callbackStatus - Success or Failure.
Jeff Johnson295189b2012-06-20 16:38:30 -07001147*
1148* Returns:
1149* nothing
1150*
1151******************************************************************************/
1152void pmcDoStartUapsdCallbacks (tHalHandle hHal, eHalStatus callbackStatus)
1153{
1154 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1155 tListElem *pEntry;
1156 tpStartUapsdEntry pStartUapsdEntry;
1157
1158 smsLog(pMac, LOG2, "PMC: entering pmcDoStartUapsdCallbacks\n");
1159
1160 /* Call the routines in the request start UAPSD callback routine list. */
1161 pEntry = csrLLRemoveHead(&pMac->pmc.requestStartUapsdList, FALSE);
1162 while (pEntry != NULL)
1163 {
1164 pStartUapsdEntry = GET_BASE_ADDR(pEntry, tStartUapsdEntry, link);
1165 pStartUapsdEntry->callbackRoutine(pStartUapsdEntry->callbackContext,
1166 callbackStatus);
1167 palFreeMemory(pMac->hHdd, pStartUapsdEntry);
1168 pEntry = csrLLRemoveHead(&pMac->pmc.requestStartUapsdList, FALSE);
1169 }
1170}
1171
1172/******************************************************************************
1173*
1174* Name: pmcEnterRequestStartUapsdState
1175*
1176* Description:
1177* Have the device enter the UAPSD State.
1178*
1179* Parameters:
1180* hHal - HAL handle for device
1181*
1182* Returns:
1183* eHAL_STATUS_SUCCESS - changing state successful
1184* eHAL_STATUS_FAILURE - changing state not successful
1185*
1186******************************************************************************/
1187eHalStatus pmcEnterRequestStartUapsdState (tHalHandle hHal)
1188{
1189 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1190 v_BOOL_t fFullPower = VOS_FALSE; //need to get back to full power state
1191
1192 smsLog(pMac, LOG2, "PMC: entering pmcEnterRequestStartUapsdState\n");
1193
1194 /* Can enter UAPSD State only from FULL_POWER or BMPS State. */
1195 switch (pMac->pmc.pmcState)
1196 {
1197 case FULL_POWER:
1198 /* Check that entry into a power save mode is allowed at this time. */
1199 if (!pmcPowerSaveCheck(hHal))
1200 {
1201 smsLog(pMac, LOGW, "PMC: Power save check failed. UAPSD request "
1202 "will be accepted and buffered\n");
1203 /* UAPSD mode will be attempted when we enter BMPS later */
1204 pMac->pmc.uapsdSessionRequired = TRUE;
1205 /* Make sure the BMPS retry timer is running */
1206 if(pmcShouldBmpsTimerRun(pMac))
1207 (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
1208 break;
1209 }
1210 else
1211 {
1212 pMac->pmc.uapsdSessionRequired = TRUE;
1213 //Check BTC state
1214#ifndef WLAN_MDM_CODE_REDUCTION_OPT
1215 if( btcIsReadyForUapsd( pMac ) )
1216#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
1217 {
1218 /* Put device in BMPS mode first. This step should NEVER fail.
1219 That is why no need to buffer the UAPSD request*/
1220 if(pmcEnterRequestBmpsState(hHal) != eHAL_STATUS_SUCCESS)
1221 {
1222 smsLog(pMac, LOGE, "PMC: Device in Full Power. Enter Request Bmps failed. "
1223 "UAPSD request will be dropped \n");
1224 return eHAL_STATUS_FAILURE;
1225 }
1226 }
1227#ifndef WLAN_MDM_CODE_REDUCTION_OPT
1228 else
1229 {
1230 (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
1231 }
1232#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
1233 }
1234 break;
1235
1236 case BMPS:
1237 //It is already in BMPS mode, check BTC state
1238#ifndef WLAN_MDM_CODE_REDUCTION_OPT
1239 if( btcIsReadyForUapsd(pMac) )
1240#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
1241 {
1242 /* Tell MAC to have device enter UAPSD mode. */
1243 if (pmcIssueCommand(hHal, eSmeCommandEnterUapsd, NULL, 0, FALSE) !=
1244 eHAL_STATUS_SUCCESS)
1245 {
1246 smsLog(pMac, LOGE, "PMC: failure to send message "
1247 "eWNI_PMC_ENTER_BMPS_REQ\n");
1248 return eHAL_STATUS_FAILURE;
1249 }
1250 }
1251#ifndef WLAN_MDM_CODE_REDUCTION_OPT
1252 else
1253 {
1254 //Not ready for UAPSD at this time, save it first and wake up the chip
1255 smsLog(pMac, LOGE, " PMC state = %d\n",pMac->pmc.pmcState);
1256 pMac->pmc.uapsdSessionRequired = TRUE;
Jeff Johnsone7245742012-09-05 17:12:55 -07001257 /* While BTC traffic is going on, STA can be in BMPS
Jeff Johnson295189b2012-06-20 16:38:30 -07001258 * and need not go to Full Power */
Jeff Johnsone7245742012-09-05 17:12:55 -07001259 //fFullPower = VOS_TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001260 }
1261#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
1262 break;
1263
1264 case REQUEST_START_UAPSD:
1265#ifndef WLAN_MDM_CODE_REDUCTION_OPT
1266 if( !btcIsReadyForUapsd(pMac) )
1267 {
1268 //BTC rejects UAPSD, bring it back to full power
1269 fFullPower = VOS_TRUE;
1270 }
1271#endif
1272 break;
1273
1274 case REQUEST_BMPS:
1275 /* Buffer request for UAPSD mode. */
1276 pMac->pmc.uapsdSessionRequired = TRUE;
1277#ifndef WLAN_MDM_CODE_REDUCTION_OPT
1278 if( !btcIsReadyForUapsd(pMac) )
1279 {
1280 //BTC rejects UAPSD, bring it back to full power
1281 fFullPower = VOS_TRUE;
1282 }
1283#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
1284 break;
1285
1286 default:
1287 smsLog(pMac, LOGE, "PMC: trying to enter UAPSD State from state %d\n",
1288 pMac->pmc.pmcState);
1289 return eHAL_STATUS_FAILURE;
1290 }
1291
1292 if(fFullPower)
1293 {
1294 if( eHAL_STATUS_PMC_PENDING != pmcRequestFullPower( pMac, NULL, NULL, eSME_REASON_OTHER ) )
1295 {
1296 //This is an error
1297 smsLog(pMac, LOGE, FL(" fail to request full power because BTC\n"));
1298 }
1299 }
1300
1301 return eHAL_STATUS_SUCCESS;
1302}
1303
1304/******************************************************************************
1305*
1306* Name: pmcEnterUapsdState
1307*
1308* Description:
1309* Have the device enter the UAPSD State.
1310*
1311* Parameters:
1312* hHal - HAL handle for device
1313*
1314* Returns:
1315* eHAL_STATUS_SUCCESS - changing state successful
1316* eHAL_STATUS_FAILURE - changing state not successful
1317*
1318******************************************************************************/
1319eHalStatus pmcEnterUapsdState (tHalHandle hHal)
1320{
1321 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1322
1323 smsLog(pMac, LOG2, "PMC: entering pmcEnterUapsdState\n");
1324
1325 /* Can enter UAPSD State only from Request UAPSD State. */
1326 if (pMac->pmc.pmcState != REQUEST_START_UAPSD )
1327 {
1328 smsLog(pMac, LOGE, "PMC: trying to enter UAPSD State from state %d\n",
1329 pMac->pmc.pmcState);
1330 return eHAL_STATUS_FAILURE;
1331 }
1332
1333 /* Change state. */
1334 pMac->pmc.pmcState = UAPSD;
1335
1336 /* Update registerd modules that we are entering UAPSD. This is
1337 only way to inform modules if PMC resumed UAPSD power save mode
1338 on its own after full power mode */
1339 pmcDoDeviceStateUpdateCallbacks(hHal, UAPSD);
Jeff Johnsone7245742012-09-05 17:12:55 -07001340
Jeff Johnson295189b2012-06-20 16:38:30 -07001341 /* If we have a reqeust for full power pending then we have to go
1342 directly into full power. */
1343 if (pMac->pmc.requestFullPowerPending)
1344 {
1345 /* Start exit UAPSD sequence now. */
1346 return pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason);
1347 }
1348
1349 return eHAL_STATUS_SUCCESS;
1350}
1351
1352
1353/******************************************************************************
1354*
1355* Name: pmcEnterRequestStopUapsdState
1356*
1357* Description:
1358* Have the device Stop the UAPSD State.
1359*
1360* Parameters:
1361* hHal - HAL handle for device
1362*
1363* Returns:
1364* eHAL_STATUS_SUCCESS - changing state successful
1365* eHAL_STATUS_FAILURE - changing state not successful
1366*
1367******************************************************************************/
1368eHalStatus pmcEnterRequestStopUapsdState (tHalHandle hHal)
1369{
1370 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1371
1372 smsLog(pMac, LOG2, "PMC: entering pmcEnterRequestStopUapsdState\n");
1373
1374 /* If already in REQUEST_STOP_UAPSD, simply return */
1375 if (pMac->pmc.pmcState == REQUEST_STOP_UAPSD)
1376 {
1377 return eHAL_STATUS_SUCCESS;
1378 }
1379
1380 /* Can enter Request Stop UAPSD State only from UAPSD */
1381 if (pMac->pmc.pmcState != UAPSD)
1382 {
1383 smsLog(pMac, LOGE, "PMC: trying to enter Request Stop UAPSD State from "
1384 "state %d\n", pMac->pmc.pmcState);
1385 return eHAL_STATUS_FAILURE;
1386 }
1387
1388 /* Tell MAC to have device exit UAPSD mode. */
1389 if (pmcIssueCommand(hHal, eSmeCommandExitUapsd, NULL, 0, FALSE) !=
1390 eHAL_STATUS_SUCCESS)
1391 {
1392 smsLog(pMac, LOGE, "PMC: failure to send message "
1393 "eWNI_PMC_EXIT_UAPSD_REQ\n");
1394 return eHAL_STATUS_FAILURE;
1395 }
1396
1397 return eHAL_STATUS_SUCCESS;
1398}
1399
1400/******************************************************************************
1401*
1402* Name: pmcEnterRequestStandbyState
1403*
1404* Description:
1405* Have the device enter the Request STANDBY State.
1406*
1407* Parameters:
1408* hHal - HAL handle for device
1409*
1410* Returns:
1411* eHAL_STATUS_SUCCESS - changing state successful
1412* eHAL_STATUS_FAILURE - changing state not successful
1413*
1414******************************************************************************/
1415eHalStatus pmcEnterRequestStandbyState (tHalHandle hHal)
1416{
1417 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1418
1419 smsLog(pMac, LOG2, "PMC: entering pmcEnterRequestStandbyState\n");
1420
1421 /* Can enter Standby State only from Full Power State. */
1422 if (pMac->pmc.pmcState != FULL_POWER)
1423 {
1424 smsLog(pMac, LOGE, "PMC: trying to enter Standby State from "
1425 "state %d\n", pMac->pmc.pmcState);
1426 return eHAL_STATUS_FAILURE;
1427 }
1428
1429 // Stop traffic timer. Just making sure timer is not running
1430 pmcStopTrafficTimer(hHal);
1431
1432 /* Tell MAC to have device enter STANDBY mode. We are using the same message
1433 as IMPS mode to avoid code changes in layer below (PE/HAL)*/
1434 if (pmcIssueCommand(hHal, eSmeCommandEnterStandby, NULL, 0, FALSE) !=
1435 eHAL_STATUS_SUCCESS)
1436 {
1437 smsLog(pMac, LOGE, "PMC: failure to send message "
1438 "eWNI_PMC_ENTER_IMPS_REQ\n");
1439 pMac->pmc.pmcState = FULL_POWER;
1440
1441 if(pmcShouldBmpsTimerRun(pMac))
1442 (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
1443 return eHAL_STATUS_FAILURE;
1444 }
Jeff Johnsone7245742012-09-05 17:12:55 -07001445
Jeff Johnson295189b2012-06-20 16:38:30 -07001446 return eHAL_STATUS_SUCCESS;
1447}
1448
1449/******************************************************************************
1450*
1451* Name: pmcEnterStandbyState
1452*
1453* Description:
1454* Have the device enter the STANDBY State.
1455*
1456* Parameters:
1457* hHal - HAL handle for device
1458*
1459* Returns:
1460* eHAL_STATUS_SUCCESS - changing state successful
1461* eHAL_STATUS_FAILURE - changing state not successful
1462*
1463******************************************************************************/
1464eHalStatus pmcEnterStandbyState (tHalHandle hHal)
1465{
1466 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1467 vos_call_status_type callType;
1468 VOS_STATUS status;
1469
1470 smsLog(pMac, LOG2, "PMC: entering pmcEnterStandbyState\n");
1471
1472 /* Can enter STANDBY State only from REQUEST_STANDBY State. */
1473 if (pMac->pmc.pmcState != REQUEST_STANDBY)
1474 {
1475 smsLog(pMac, LOGE, "PMC: trying to enter STANDBY State from state %d\n",
1476 pMac->pmc.pmcState);
1477 return eHAL_STATUS_FAILURE;
1478 }
1479
1480 /* Change state. */
1481 pMac->pmc.pmcState = STANDBY;
1482
1483 /* If we have a reqeust for full power pending then we have to go
1484 directly into full power. */
1485 if (pMac->pmc.requestFullPowerPending)
1486 {
1487 /* Start exit STANDBY sequence now. */
1488 return pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason);
1489 }
1490
1491 //Note that RF supplies are not voted off if there is already a pending request
1492 //for full power
1493 status = vos_chipVoteOffRFSupply(&callType, NULL, NULL);
1494 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
1495
1496 status = vos_chipVoteOffXOBuffer(&callType, NULL, NULL);
1497 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
1498
1499 pMac->pmc.rfSuppliesVotedOff= TRUE;
1500
1501 return eHAL_STATUS_SUCCESS;
1502}
1503
1504/******************************************************************************
1505*
1506* Name: pmcDoStandbyCallbacks
1507*
1508* Description:
Jeff Johnsone7245742012-09-05 17:12:55 -07001509* Call the registered Standby callback routines
Jeff Johnson295189b2012-06-20 16:38:30 -07001510*
1511* Parameters:
1512* hHal - HAL handle for device
1513* callbackStatus - Success or Failure.
1514*
1515* Returns:
1516* nothing
1517*
1518******************************************************************************/
1519void pmcDoStandbyCallbacks (tHalHandle hHal, eHalStatus callbackStatus)
1520{
1521 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
Jeff Johnsone7245742012-09-05 17:12:55 -07001522
Jeff Johnson295189b2012-06-20 16:38:30 -07001523 smsLog(pMac, LOG2, "PMC: entering pmcDoStandbyCallbacks\n");
1524
1525 /* Call Standby callback routine. */
1526 if (pMac->pmc.standbyCallbackRoutine != NULL)
1527 pMac->pmc.standbyCallbackRoutine(pMac->pmc.standbyCallbackContext, callbackStatus);
1528 pMac->pmc.standbyCallbackRoutine = NULL;
1529 pMac->pmc.standbyCallbackContext = NULL;
1530}
1531
1532/******************************************************************************
1533*
1534* Name: pmcGetPmcState
1535*
1536* Description:
1537* Return the PMC state
1538*
1539* Parameters:
1540* hHal - HAL handle for device
1541*
1542* Returns:
1543* tPmcState (one of IMPS, REQUEST_IMPS, BMPS, REQUEST_BMPS etc)
1544*
1545******************************************************************************/
1546tPmcState pmcGetPmcState (tHalHandle hHal)
1547{
1548 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
Jeff Johnsone7245742012-09-05 17:12:55 -07001549 return pMac->pmc.pmcState;
Jeff Johnson295189b2012-06-20 16:38:30 -07001550}
1551
1552const char* pmcGetPmcStateStr(tPmcState state)
1553{
1554 switch(state)
1555 {
1556 case STOPPED:
1557 return "STOPPED";
1558 case FULL_POWER:
1559 return "FULL_POWER";
1560 case LOW_POWER:
1561 return "LOW_POWER";
1562 case IMPS:
1563 return "IMPS";
1564 case BMPS:
1565 return "BMPS";
1566 case UAPSD:
1567 return "UAPSD";
1568 case STANDBY:
1569 return "STANDBY";
1570 case REQUEST_IMPS:
1571 return "REQUEST_IMPS";
1572 case REQUEST_BMPS:
1573 return "REQUEST_BMPS";
1574 case REQUEST_START_UAPSD:
1575 return "REQUEST_START_UAPSD";
1576 case REQUEST_STOP_UAPSD:
1577 return "REQUEST_STOP_UAPSD";
1578 case REQUEST_FULL_POWER:
1579 return "REQUEST_FULL_POWER";
1580 case REQUEST_STANDBY:
1581 return "REQUEST_STANDBY";
1582 case REQUEST_ENTER_WOWL:
1583 return "REQUEST_ENTER_WOWL";
1584 case REQUEST_EXIT_WOWL:
1585 return "REQUEST_EXIT_WOWL";
1586 case WOWL:
1587 return "WOWL";
1588 default:
1589 break;
1590 }
1591
1592 return "UNKNOWN";
1593}
1594
1595void pmcDoDeviceStateUpdateCallbacks (tHalHandle hHal, tPmcState state)
1596{
1597 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1598 tListElem *pEntry;
1599 tpDeviceStateUpdateIndEntry pDeviceStateUpdateIndEntry;
1600 void (*callbackRoutine) (void *callbackContext, tPmcState pmcState);
1601
1602 smsLog(pMac, LOG2, FL("PMC - Update registered modules of new device "
1603 "state: %s\n"), pmcGetPmcStateStr(state));
1604
1605 /* Call the routines in the update device state routine list. */
1606 pEntry = csrLLPeekHead(&pMac->pmc.deviceStateUpdateIndList, FALSE);
1607 while (pEntry != NULL)
1608 {
1609 pDeviceStateUpdateIndEntry = GET_BASE_ADDR(pEntry, tDeviceStateUpdateIndEntry, link);
1610 callbackRoutine = pDeviceStateUpdateIndEntry->callbackRoutine;
1611 callbackRoutine(pDeviceStateUpdateIndEntry->callbackContext, state);
1612 pEntry = csrLLNext(&pMac->pmc.deviceStateUpdateIndList, pEntry, FALSE);
1613 }
1614}
1615
1616/******************************************************************************
1617*
1618* Name: pmcRequestEnterWowlState
1619*
1620* Description:
1621* Have the device enter the WOWL State.
1622*
1623* Parameters:
1624* hHal - HAL handle for device
1625*
1626* Returns:
1627* eHAL_STATUS_SUCCESS - WOWL mode will be entered
1628* eHAL_STATUS_FAILURE - WOWL mode cannot be entered
1629*
1630******************************************************************************/
1631eHalStatus pmcRequestEnterWowlState(tHalHandle hHal, tpSirSmeWowlEnterParams wowlEnterParams)
1632{
1633 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1634 smsLog(pMac, LOG2, "PMC: entering pmcRequestEnterWowlState\n");
1635
1636 switch (pMac->pmc.pmcState)
1637 {
1638 case FULL_POWER:
1639 /* Put device in BMPS mode first. This step should NEVER fail. */
1640 if(pmcEnterRequestBmpsState(hHal) != eHAL_STATUS_SUCCESS)
1641 {
1642 smsLog(pMac, LOGE, "PMC: Device in Full Power. pmcEnterRequestBmpsState failed. "
1643 "Cannot enter WOWL\n");
1644 return eHAL_STATUS_FAILURE;
1645 }
1646 break;
1647
1648 case REQUEST_BMPS:
1649 smsLog(pMac, LOGW, "PMC: BMPS transaction going on. WOWL request "
Jeff Johnsone7245742012-09-05 17:12:55 -07001650 "will be buffered\n");
Jeff Johnson295189b2012-06-20 16:38:30 -07001651 break;
1652
1653 case BMPS:
1654 case WOWL:
1655 /* Tell MAC to have device enter WOWL mode. Note: We accept WOWL request
1656 when we are in WOWL mode. This allows HDD to change WOWL configuration
1657 without having to exit WOWL mode */
1658 if (pmcIssueCommand(hHal, eSmeCommandEnterWowl, wowlEnterParams, sizeof(tSirSmeWowlEnterParams), FALSE) !=
1659 eHAL_STATUS_SUCCESS)
1660 {
1661 smsLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_WOWL_REQ\n");
1662 return eHAL_STATUS_FAILURE;
1663 }
1664 break;
1665
1666 case REQUEST_ENTER_WOWL:
1667 //Multiple enter WOWL requests at the same time are not accepted
1668 smsLog(pMac, LOGE, "PMC: Enter WOWL transaction already going on. New WOWL request "
1669 "will be rejected\n");
1670 return eHAL_STATUS_FAILURE;
1671
1672 case REQUEST_EXIT_WOWL:
1673 smsLog(pMac, LOGW, "PMC: Exit WOWL transaction going on. New WOWL request "
Jeff Johnsone7245742012-09-05 17:12:55 -07001674 "will be buffered\n");
Jeff Johnson295189b2012-06-20 16:38:30 -07001675 break;
1676
1677 default:
1678 smsLog(pMac, LOGE, "PMC: Trying to enter WOWL State from state %s\n",
1679 pmcGetPmcStateStr(pMac->pmc.pmcState));
1680 return eHAL_STATUS_FAILURE;
1681 }
1682
1683 return eHAL_STATUS_SUCCESS;
1684}
1685
1686/******************************************************************************
1687*
1688* Name: pmcEnterWowlState
1689*
1690* Description:
1691* Have the device enter the WOWL State.
1692*
1693* Parameters:
1694* hHal - HAL handle for device
1695*
1696* Returns:
1697* eHAL_STATUS_SUCCESS - changing state successful
1698* eHAL_STATUS_FAILURE - changing state not successful
1699*
1700******************************************************************************/
1701eHalStatus pmcEnterWowlState (tHalHandle hHal)
1702{
1703 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1704
1705 smsLog(pMac, LOG2, "PMC: entering pmcEnterWowlState\n");
1706
1707 /* Can enter WOWL State only from Request WOWL State. */
1708 if (pMac->pmc.pmcState != REQUEST_ENTER_WOWL )
1709 {
1710 smsLog(pMac, LOGP, "PMC: trying to enter WOWL State from state %d\n",
1711 pMac->pmc.pmcState);
1712 return eHAL_STATUS_FAILURE;
1713 }
1714
1715 /* Change state. */
1716 pMac->pmc.pmcState = WOWL;
1717
1718 /* Clear the buffered command for WOWL */
1719 pMac->pmc.wowlModeRequired = FALSE;
1720
1721 /* If we have a reqeust for full power pending then we have to go
1722 directly into full power. */
1723 if (pMac->pmc.requestFullPowerPending)
1724 {
1725 /* Start exit Wowl sequence now. */
1726 return pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason);
1727 }
1728
1729 return eHAL_STATUS_SUCCESS;
1730}
1731
1732/******************************************************************************
1733*
1734* Name: pmcRequestExitWowlState
1735*
1736* Description:
1737* Have the device exit WOWL State.
1738*
1739* Parameters:
1740* hHal - HAL handle for device
1741*
1742* Returns:
1743* eHAL_STATUS_SUCCESS - Exit WOWL successful
1744* eHAL_STATUS_FAILURE - Exit WOWL unsuccessful
1745*
1746******************************************************************************/
1747eHalStatus pmcRequestExitWowlState(tHalHandle hHal)
1748{
1749 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1750
1751 smsLog(pMac, LOG2, "PMC: entering pmcRequestExitWowlState\n");
1752
1753 switch (pMac->pmc.pmcState)
1754 {
1755 case WOWL:
1756 /* Tell MAC to have device exit WOWL mode. */
1757 if (pmcIssueCommand(hHal, eSmeCommandExitWowl, NULL, 0, FALSE) !=
1758 eHAL_STATUS_SUCCESS)
1759 {
1760 smsLog(pMac, LOGP, "PMC: failure to send message eWNI_PMC_EXIT_WOWL_REQ\n");
1761 return eHAL_STATUS_FAILURE;
1762 }
1763 break;
1764
1765 case REQUEST_ENTER_WOWL:
1766 smsLog(pMac, LOGP, "PMC: Rcvd exit WOWL even before enter WOWL was completed\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001767 return eHAL_STATUS_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001768
1769 default:
1770 smsLog(pMac, LOGW, "PMC: Got exit WOWL in state %s. Nothing to do as already out of WOWL\n",
1771 pmcGetPmcStateStr(pMac->pmc.pmcState));
1772 break;
1773 }
1774
1775 return eHAL_STATUS_SUCCESS;
1776}
1777
1778/******************************************************************************
1779*
1780* Name: pmcDoEnterWowlCallbacks
1781*
1782* Description:
1783* Invoke Enter WOWL callbacks
1784*
1785* Parameters:
1786* hHal - HAL handle for device
1787*
1788* Returns: None
1789*
1790******************************************************************************/
1791void pmcDoEnterWowlCallbacks (tHalHandle hHal, eHalStatus callbackStatus)
1792{
1793 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
Jeff Johnsone7245742012-09-05 17:12:55 -07001794
Jeff Johnson295189b2012-06-20 16:38:30 -07001795 smsLog(pMac, LOG2, "PMC: entering pmcDoWowlCallbacks\n");
1796
1797 /* Call Wowl callback routine. */
1798 if (pMac->pmc.enterWowlCallbackRoutine != NULL)
1799 pMac->pmc.enterWowlCallbackRoutine(pMac->pmc.enterWowlCallbackContext, callbackStatus);
1800
1801 pMac->pmc.enterWowlCallbackRoutine = NULL;
1802 pMac->pmc.enterWowlCallbackContext = NULL;
1803}
1804
1805
1806static void pmcProcessDeferredMsg( tpAniSirGlobal pMac )
1807{
1808 tPmcDeferredMsg *pDeferredMsg;
1809 tListElem *pEntry;
1810
1811 while( NULL != ( pEntry = csrLLRemoveHead( &pMac->pmc.deferredMsgList, eANI_BOOLEAN_TRUE ) ) )
1812 {
1813 pDeferredMsg = GET_BASE_ADDR( pEntry, tPmcDeferredMsg, link );
1814 switch (pDeferredMsg->messageType)
1815 {
1816 case eWNI_PMC_WOWL_ADD_BCAST_PTRN:
1817 VOS_ASSERT( pDeferredMsg->size == sizeof(tSirWowlAddBcastPtrn) );
Jeff Johnsone7245742012-09-05 17:12:55 -07001818 if (pmcSendMessage(pMac, eWNI_PMC_WOWL_ADD_BCAST_PTRN,
Jeff Johnson295189b2012-06-20 16:38:30 -07001819 &pDeferredMsg->u.wowlAddPattern, sizeof(tSirWowlAddBcastPtrn))
1820 != eHAL_STATUS_SUCCESS)
1821 {
1822 smsLog(pMac, LOGE, FL("Send of eWNI_PMC_WOWL_ADD_BCAST_PTRN to PE failed\n"));
1823 }
1824 break;
1825
1826 case eWNI_PMC_WOWL_DEL_BCAST_PTRN:
1827 VOS_ASSERT( pDeferredMsg->size == sizeof(tSirWowlDelBcastPtrn) );
Jeff Johnsone7245742012-09-05 17:12:55 -07001828 if (pmcSendMessage(pMac, eWNI_PMC_WOWL_DEL_BCAST_PTRN,
Jeff Johnson295189b2012-06-20 16:38:30 -07001829 &pDeferredMsg->u.wowlDelPattern, sizeof(tSirWowlDelBcastPtrn))
1830 != eHAL_STATUS_SUCCESS)
1831 {
1832 smsLog(pMac, LOGE, FL("Send of eWNI_PMC_WOWL_ADD_BCAST_PTRN to PE failed\n"));
1833 }
1834 break;
1835
1836 case eWNI_PMC_PWR_SAVE_CFG:
1837 VOS_ASSERT( pDeferredMsg->size == sizeof(tSirPowerSaveCfg) );
Jeff Johnsone7245742012-09-05 17:12:55 -07001838 if (pmcSendMessage(pMac, eWNI_PMC_PWR_SAVE_CFG,
1839 &pDeferredMsg->u.powerSaveConfig, sizeof(tSirPowerSaveCfg))
Jeff Johnson295189b2012-06-20 16:38:30 -07001840 != eHAL_STATUS_SUCCESS)
1841 {
1842 smsLog(pMac, LOGE, FL("Send of eWNI_PMC_PWR_SAVE_CFG to PE failed\n"));
1843 }
1844 break;
1845
1846 default:
1847 smsLog(pMac, LOGE, FL("unknown message (%d)\n"), pDeferredMsg->messageType);
1848 break;
1849 }
1850 //Need to free the memory here
1851 palFreeMemory( pMac->hHdd, pDeferredMsg );
1852 } //while
1853}
1854
1855
1856eHalStatus pmcDeferMsg( tpAniSirGlobal pMac, tANI_U16 messageType, void *pData, tANI_U32 size)
1857{
1858 tPmcDeferredMsg *pDeferredMsg;
1859 eHalStatus status;
1860
1861 if( !HAL_STATUS_SUCCESS( palAllocateMemory( pMac->hHdd, (void **)&pDeferredMsg, sizeof(tPmcDeferredMsg) ) ) )
1862 {
1863 smsLog(pMac, LOGE, FL("Cannot allocate memory for callback context\n"));
1864 return eHAL_STATUS_RESOURCES;
1865 }
1866 palZeroMemory( pMac->hHdd, pDeferredMsg, sizeof(tPmcDeferredMsg) );
1867 pDeferredMsg->messageType = messageType;
1868 pDeferredMsg->size = (tANI_U16)size;
1869 if( pData )
1870 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001871 if( !HAL_STATUS_SUCCESS( palCopyMemory( pMac->hHdd, &pDeferredMsg->u.data,
Jeff Johnson295189b2012-06-20 16:38:30 -07001872 pData, size ) ) )
1873 {
1874 smsLog(pMac, LOGE, FL("Cannot copy pattern for callback context\n"));
1875 palFreeMemory( pMac->hHdd, pDeferredMsg );
1876 return eHAL_STATUS_FAILURE;
1877 }
1878 }
1879 csrLLInsertTail( &pMac->pmc.deferredMsgList, &pDeferredMsg->link, eANI_BOOLEAN_TRUE );
Jeff Johnsone7245742012-09-05 17:12:55 -07001880 //No callback is needed. The messages are put into deferred queue and be processed first
Jeff Johnson295189b2012-06-20 16:38:30 -07001881 //when enter full power is complete.
1882 status = pmcRequestFullPower( pMac, NULL, NULL, eSME_REASON_OTHER );
1883 if( eHAL_STATUS_PMC_PENDING != status )
1884 {
1885 //either fail or already in full power
1886 if( csrLLRemoveEntry( &pMac->pmc.deferredMsgList, &pDeferredMsg->link, eANI_BOOLEAN_TRUE ) )
1887 {
1888 palFreeMemory( pMac->hHdd, pDeferredMsg );
1889 }
1890 if( !HAL_STATUS_SUCCESS( status ) )
1891 {
1892 smsLog(pMac, LOGE, FL("failed to request full power status = %d\n"), status);
1893 }
1894 }
1895
1896 return (status);
1897}
1898
1899void pmcReleaseCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand )
1900{
1901 if(!pCommand->u.pmcCmd.fReleaseWhenDone)
1902 {
1903 //This is a normal command, put it back to the free lsit
1904 pCommand->u.pmcCmd.size = 0;
1905 smeReleaseCommand( pMac, pCommand );
1906 }
1907 else
1908 {
1909 //this is a specially allocated comamnd due to out of command buffer. free it.
1910 palFreeMemory(pMac->hHdd, pCommand);
1911 }
1912}
1913
1914
1915//this function is used to abort a command where the normal processing of the command
1916//is terminated without going through the normal path. it is here to take care of callbacks for
1917//the command, if applicable.
1918void pmcAbortCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fStopping )
1919{
1920 if( eSmePmcCommandMask & pCommand->command )
1921 {
1922 if( !fStopping )
1923 {
1924 switch( pCommand->command )
1925 {
1926 case eSmeCommandEnterImps:
1927 smsLog(pMac, LOGE, FL("aborting request to enter IMPS\n"));
1928 pmcEnterFullPowerState(pMac);
1929 break;
1930
1931 case eSmeCommandExitImps:
1932 smsLog(pMac, LOGE, FL("aborting request to exit IMPS \n"));
1933 pmcEnterFullPowerState(pMac);
1934 break;
1935
1936 case eSmeCommandEnterBmps:
1937 smsLog(pMac, LOGE, FL("aborting request to enter BMPS \n"));
1938 pMac->pmc.bmpsRequestQueued = eANI_BOOLEAN_FALSE;
1939 pmcEnterFullPowerState(pMac);
1940 pmcDoBmpsCallbacks(pMac, eHAL_STATUS_FAILURE);
1941 break;
1942
1943 case eSmeCommandExitBmps:
1944 smsLog(pMac, LOGE, FL("aborting request to exit BMPS \n"));
1945 pmcEnterFullPowerState(pMac);
1946 break;
1947
1948 case eSmeCommandEnterUapsd:
1949 smsLog(pMac, LOGE, FL("aborting request to enter UAPSD \n"));
1950 //Since there is no retry for UAPSD, tell the requester here we are done with failure
1951 pMac->pmc.uapsdSessionRequired = FALSE;
1952 pmcDoStartUapsdCallbacks(pMac, eHAL_STATUS_FAILURE);
1953 break;
1954
1955 case eSmeCommandExitUapsd:
1956 smsLog(pMac, LOGE, FL("aborting request to exit UAPSD \n"));
1957 break;
1958
1959 case eSmeCommandEnterWowl:
1960 smsLog(pMac, LOGE, FL("aborting request to enter WOWL \n"));
1961 pmcDoEnterWowlCallbacks(pMac, eHAL_STATUS_FAILURE);
1962 break;
1963
1964 case eSmeCommandExitWowl:
1965 smsLog(pMac, LOGE, FL("aborting request to exit WOWL \n"));
1966 break;
1967
1968 case eSmeCommandEnterStandby:
1969 smsLog(pMac, LOGE, FL("aborting request to enter Standby \n"));
1970 pmcDoStandbyCallbacks(pMac, eHAL_STATUS_FAILURE);
1971 break;
1972
1973 default:
1974 smsLog(pMac, LOGE, FL("Request for PMC command (%d) is dropped\n"), pCommand->command);
1975 break;
1976 }
1977 }// !stopping
1978 pmcReleaseCommand( pMac, pCommand );
1979 }
1980}
1981
1982
1983
1984//These commands are not supposed to fail due to out of command buffer,
Jeff Johnsone7245742012-09-05 17:12:55 -07001985//otherwise other commands are not executed and no command is released. It will be deadlock.
Jeff Johnson295189b2012-06-20 16:38:30 -07001986#define PMC_IS_COMMAND_CANNOT_FAIL(cmdType)\
1987 ( (eSmeCommandEnterStandby == (cmdType )) ||\
1988 (eSmeCommandExitImps == (cmdType )) ||\
1989 (eSmeCommandExitBmps == (cmdType )) ||\
1990 (eSmeCommandExitUapsd == (cmdType )) ||\
1991 (eSmeCommandExitWowl == (cmdType )) )
1992
Jeff Johnsone7245742012-09-05 17:12:55 -07001993eHalStatus pmcPrepareCommand( tpAniSirGlobal pMac, eSmeCommandType cmdType, void *pvParam,
Jeff Johnson295189b2012-06-20 16:38:30 -07001994 tANI_U32 size, tSmeCmd **ppCmd )
1995{
1996 eHalStatus status = eHAL_STATUS_RESOURCES;
1997 tSmeCmd *pCommand = NULL;
1998
1999 VOS_ASSERT( ppCmd );
2000 do
2001 {
2002 pCommand = smeGetCommandBuffer( pMac );
2003 if ( pCommand )
2004 {
2005 //Make sure it will be put back to the list
2006 pCommand->u.pmcCmd.fReleaseWhenDone = FALSE;
2007 }
2008 else
2009 {
2010 smsLog( pMac, LOGE, FL(" fail to get command buffer for command 0x%X curState = %d"), cmdType, pMac->pmc.pmcState );
2011 //For certain PMC command, we cannot fail
2012 if( PMC_IS_COMMAND_CANNOT_FAIL(cmdType) )
2013 {
2014 smsLog( pMac, LOGE, FL(" command 0x%X cannot fail try allocating memory for it"), cmdType );
2015 status = palAllocateMemory(pMac->hHdd, (void **)&pCommand, sizeof(tSmeCmd));
2016 if(!HAL_STATUS_SUCCESS(status))
2017 {
Jeff Johnsone7245742012-09-05 17:12:55 -07002018 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, "%s fail to allocate memory for command (0x%X)",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002019 __func__, cmdType);
Jeff Johnson295189b2012-06-20 16:38:30 -07002020 pCommand = NULL;
2021 break;
2022 }
2023 palZeroMemory(pMac->hHdd, pCommand, sizeof(tSmeCmd));
2024 //Make sure it will be free when it is done
2025 pCommand->u.pmcCmd.fReleaseWhenDone = TRUE;
2026 }
2027 else
2028 {
2029 break;
2030 }
2031 }
2032 pCommand->command = cmdType;
2033 pCommand->u.pmcCmd.size = size;
2034 //Initialize the reason code here. It may be overwritten later when
2035 //a particular reason is needed.
2036 pCommand->u.pmcCmd.fullPowerReason = eSME_REASON_OTHER;
2037 switch ( cmdType )
2038 {
2039 case eSmeCommandEnterImps:
2040 case eSmeCommandExitImps:
2041 case eSmeCommandEnterBmps:
2042 case eSmeCommandEnterUapsd:
2043 case eSmeCommandEnterStandby:
2044 status = eHAL_STATUS_SUCCESS;
2045 break;
2046
2047 case eSmeCommandExitUapsd:
2048 case eSmeCommandExitWowl:
2049 status = eHAL_STATUS_SUCCESS;
2050 if( pvParam )
2051 {
2052 pCommand->u.pmcCmd.fullPowerReason = *( (tRequestFullPowerReason *)pvParam );
2053 }
2054 break;
2055
2056 case eSmeCommandExitBmps:
2057 status = eHAL_STATUS_SUCCESS;
2058 if( pvParam )
2059 {
2060 pCommand->u.pmcCmd.u.exitBmpsInfo = *( (tExitBmpsInfo *)pvParam );
2061 pCommand->u.pmcCmd.fullPowerReason = pCommand->u.pmcCmd.u.exitBmpsInfo.exitBmpsReason;
2062 }
2063 else
2064 {
2065 smsLog( pMac, LOGE, (" exit BMPS must have a reason code\n") );
2066 }
2067 break;
2068
2069 case eSmeCommandEnterWowl:
2070 status = eHAL_STATUS_SUCCESS;
2071 if( pvParam )
2072 {
2073 pCommand->u.pmcCmd.u.enterWowlInfo = *( ( tSirSmeWowlEnterParams * )pvParam );
2074 }
2075 break;
2076
2077 default:
2078 smsLog( pMac, LOGE, FL(" invalid command type %d\n"), cmdType );
2079 status = eHAL_STATUS_INVALID_PARAMETER;
2080 break;
2081 }
2082
2083 } while( 0 );
2084
2085 if( HAL_STATUS_SUCCESS( status ) && pCommand )
2086 {
2087 *ppCmd = pCommand;
2088 }
2089 else if( pCommand )
2090 {
2091 pmcReleaseCommand( pMac, pCommand );
2092 }
2093
2094 return (status);
2095}
2096
2097
Jeff Johnsone7245742012-09-05 17:12:55 -07002098eHalStatus pmcIssueCommand( tpAniSirGlobal pMac, eSmeCommandType cmdType, void *pvParam,
Jeff Johnson295189b2012-06-20 16:38:30 -07002099 tANI_U32 size, tANI_BOOLEAN fPutToListHead )
2100{
2101 eHalStatus status = eHAL_STATUS_RESOURCES;
2102 tSmeCmd *pCommand = NULL;
2103
2104 status = pmcPrepareCommand( pMac, cmdType, pvParam, size, &pCommand );
2105 if( HAL_STATUS_SUCCESS( status ) && pCommand )
2106 {
2107 smePushCommand( pMac, pCommand, fPutToListHead );
2108 }
2109
2110 return( status );
2111}
2112
2113
2114
2115tANI_BOOLEAN pmcProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand )
2116{
2117 eHalStatus status = eHAL_STATUS_SUCCESS;
Jeff Johnson43971f52012-07-17 12:26:56 -07002118 VOS_STATUS vstatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07002119 tANI_BOOLEAN fRemoveCmd = eANI_BOOLEAN_TRUE;
2120
2121 do
2122 {
2123 switch ( pCommand->command )
2124 {
2125 case eSmeCommandEnterImps:
2126 if( FULL_POWER == pMac->pmc.pmcState )
2127 {
2128 status = pmcEnterImpsCheck( pMac );
2129 if( HAL_STATUS_SUCCESS( status ) )
2130 {
2131 /* Change state. */
2132 pMac->pmc.pmcState = REQUEST_IMPS;
2133 status = pmcSendMessage(pMac, eWNI_PMC_ENTER_IMPS_REQ, NULL, 0);
2134 if( HAL_STATUS_SUCCESS( status ) )
2135 {
2136 /* If we already went back Full Power State (meaning that request did not
2137 get as far as the device) then we are not successfull. */
2138 if ( FULL_POWER != pMac->pmc.pmcState )
2139 {
2140 fRemoveCmd = eANI_BOOLEAN_FALSE;
2141 }
2142 }
2143 }
2144 if( !HAL_STATUS_SUCCESS( status ) )
2145 {
2146 smsLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_IMPS_REQ or pmcEnterImpsCheck failed\n");
2147 pmcEnterFullPowerState( pMac );
2148 if(pmcShouldBmpsTimerRun(pMac))
2149 (void)pmcStartTrafficTimer(pMac, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
2150 }
2151 }//full_power
2152 break;
2153
2154 case eSmeCommandExitImps:
2155 pMac->pmc.requestFullPowerPending = FALSE;
2156 if( ( IMPS == pMac->pmc.pmcState ) || ( STANDBY == pMac->pmc.pmcState ) )
2157 {
2158 //Check state before sending message. The state may change after that
2159 if( STANDBY == pMac->pmc.pmcState )
2160 {
2161 //Enable Idle scan in CSR
2162 csrScanResumeIMPS(pMac);
2163 }
2164
2165 status = pmcSendMessage(pMac, eWNI_PMC_EXIT_IMPS_REQ, NULL, 0);
2166 if ( HAL_STATUS_SUCCESS( status ) )
2167 {
2168 pMac->pmc.pmcState = REQUEST_FULL_POWER;
Mohit Khanna23863762012-09-11 17:40:09 -07002169 smsLog(pMac, LOG2, FL("eWNI_PMC_EXIT_IMPS_REQ sent to PE\n"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002170 fRemoveCmd = eANI_BOOLEAN_FALSE;
2171 }
2172 else
2173 {
Jeff Johnsone7245742012-09-05 17:12:55 -07002174 smsLog(pMac, LOGE, FL("eWNI_PMC_EXIT_IMPS_REQ fail to be sent to PE status %d\n"), status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002175 //Callbacks are called with success srarus, do we need to pass in real status??
2176 pmcEnterFullPowerState(pMac);
2177 }
2178 }
2179 break;
2180
2181 case eSmeCommandEnterBmps:
2182 if( FULL_POWER == pMac->pmc.pmcState )
2183 {
2184 //This function will not return success because the pmc state is not BMPS
2185 status = pmcEnterBmpsCheck( pMac );
2186 if( HAL_STATUS_SUCCESS( status ) )
2187 {
2188 /* Change PMC state */
2189 pMac->pmc.pmcState = REQUEST_BMPS;
Mohit Khanna23863762012-09-11 17:40:09 -07002190 smsLog(pMac, LOG2, "PMC: Enter BMPS req done: Force XO Core ON\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07002191 vstatus = vos_chipVoteXOCore(NULL, NULL, NULL, VOS_TRUE);
Jeff Johnson43971f52012-07-17 12:26:56 -07002192 if ( !VOS_IS_STATUS_SUCCESS(vstatus) )
Jeff Johnson295189b2012-06-20 16:38:30 -07002193 {
2194 smsLog(pMac, LOGE, "Could not turn XO Core ON. Can't go to BMPS\n");
2195 }
2196 else /* XO Core turn ON was successful */
2197 {
2198 /* Tell MAC to have device enter BMPS mode. */
2199 status = pmcSendMessage(pMac, eWNI_PMC_ENTER_BMPS_REQ, NULL, 0);
2200 if ( HAL_STATUS_SUCCESS( status ) )
2201 {
2202 fRemoveCmd = eANI_BOOLEAN_FALSE;
2203 }
2204 else
2205 {
2206 smsLog(pMac, LOGE, "Fail to send enter BMPS msg to PE\n");
2207 /* Cancel the vote for XO Core */
2208 smsLog(pMac, LOGW, "In module init: Cancel the vote for XO CORE ON "
2209 "since send enter bmps failed\n");
2210 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
2211 {
2212 smsLog(pMac, LOGE, "Could not cancel XO Core ON vote."
2213 "Not returning failure."
2214 "Power consumed will be high\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07002215 }
2216
Jeff Johnson295189b2012-06-20 16:38:30 -07002217 }
2218 }
2219 }
2220 if( !HAL_STATUS_SUCCESS( status ) )
2221 {
2222 smsLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_BMPS_REQ status %d\n", status);
2223 pMac->pmc.bmpsRequestQueued = eANI_BOOLEAN_FALSE;
2224 pmcEnterFullPowerState(pMac);
2225 //Do not call UAPSD callback here since it may be retried
2226 pmcDoBmpsCallbacks(pMac, eHAL_STATUS_FAILURE);
2227 if(pmcShouldBmpsTimerRun(pMac))
2228 (void)pmcStartTrafficTimer(pMac, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
2229 }
2230 }
2231 break;
2232
2233 case eSmeCommandExitBmps:
2234 if( BMPS == pMac->pmc.pmcState )
2235 {
2236 pMac->pmc.requestFullPowerPending = FALSE;
2237
Jeff Johnsone7245742012-09-05 17:12:55 -07002238 status = pmcSendMessage( pMac, eWNI_PMC_EXIT_BMPS_REQ,
Jeff Johnson295189b2012-06-20 16:38:30 -07002239 &pCommand->u.pmcCmd.u.exitBmpsInfo, sizeof(tExitBmpsInfo) );
2240 if ( HAL_STATUS_SUCCESS( status ) )
2241 {
2242 pMac->pmc.pmcState = REQUEST_FULL_POWER;
2243 fRemoveCmd = eANI_BOOLEAN_FALSE;
Mohit Khanna23863762012-09-11 17:40:09 -07002244 smsLog(pMac, LOG2, FL("eWNI_PMC_EXIT_BMPS_REQ sent to PE\n"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002245
2246 }
2247 else
2248 {
2249 smsLog(pMac, LOGE, FL("eWNI_PMC_EXIT_BMPS_REQ fail to be sent to PE status %d\n"), status);
2250 pmcEnterFullPowerState(pMac);
2251 }
2252 }
2253 break;
2254
2255 case eSmeCommandEnterUapsd:
2256 if( BMPS == pMac->pmc.pmcState )
2257 {
2258 pMac->pmc.uapsdSessionRequired = TRUE;
2259 status = pmcSendMessage(pMac, eWNI_PMC_ENTER_UAPSD_REQ, NULL, 0);
2260 if ( HAL_STATUS_SUCCESS( status ) )
2261 {
2262 pMac->pmc.pmcState = REQUEST_START_UAPSD;
2263 fRemoveCmd = eANI_BOOLEAN_FALSE;
2264 }
2265 else
2266 {
2267 smsLog(pMac, LOGE, "PMC: failure to send message "
2268 "eWNI_PMC_ENTER_BMPS_REQ\n");
2269 //there is no retry for re-entering UAPSD so tell the requester we are done witgh failure.
2270 pMac->pmc.uapsdSessionRequired = FALSE;
2271 pmcDoStartUapsdCallbacks(pMac, eHAL_STATUS_FAILURE);
2272 }
2273 }
2274 break;
2275
2276 case eSmeCommandExitUapsd:
2277 if( UAPSD == pMac->pmc.pmcState )
2278 {
2279 pMac->pmc.requestFullPowerPending = FALSE;
2280 /* If already in REQUEST_STOP_UAPSD, simply return */
2281 if (pMac->pmc.pmcState == REQUEST_STOP_UAPSD)
2282 {
2283 break;
2284 }
2285
2286 /* Tell MAC to have device exit UAPSD mode. */
2287 status = pmcSendMessage(pMac, eWNI_PMC_EXIT_UAPSD_REQ, NULL, 0);
2288 if ( HAL_STATUS_SUCCESS( status ) )
2289 {
2290 /* Change state. Note that device will be put in BMPS state at the
2291 end of REQUEST_STOP_UAPSD state even if response is a failure*/
2292 pMac->pmc.pmcState = REQUEST_STOP_UAPSD;
2293 pMac->pmc.requestFullPowerPending = TRUE;
2294 pMac->pmc.requestFullPowerReason = pCommand->u.pmcCmd.fullPowerReason;
2295 fRemoveCmd = eANI_BOOLEAN_FALSE;
2296 }
2297 else
2298 {
2299 smsLog(pMac, LOGE, "PMC: failure to send message "
2300 "eWNI_PMC_EXIT_UAPSD_REQ\n");
2301 pmcEnterBmpsState(pMac);
2302 }
2303 }
2304
2305 break;
2306
2307 case eSmeCommandEnterWowl:
2308 if( ( BMPS == pMac->pmc.pmcState ) || ( WOWL == pMac->pmc.pmcState ) )
2309 {
Jeff Johnsone7245742012-09-05 17:12:55 -07002310 status = pmcSendMessage(pMac, eWNI_PMC_ENTER_WOWL_REQ,
Jeff Johnson295189b2012-06-20 16:38:30 -07002311 &pCommand->u.pmcCmd.u.enterWowlInfo, sizeof(tSirSmeWowlEnterParams));
2312 if ( HAL_STATUS_SUCCESS( status ) )
2313 {
2314 pMac->pmc.pmcState = REQUEST_ENTER_WOWL;
2315 fRemoveCmd = eANI_BOOLEAN_FALSE;
2316 }
2317 else
2318 {
2319 smsLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_WOWL_REQ\n");
2320 pmcDoEnterWowlCallbacks(pMac, eHAL_STATUS_FAILURE);
2321 }
2322 }
2323 else
2324 {
2325 fRemoveCmd = eANI_BOOLEAN_TRUE;
2326 }
2327 break;
2328
2329 case eSmeCommandExitWowl:
2330 if( WOWL == pMac->pmc.pmcState )
2331 {
2332 pMac->pmc.requestFullPowerPending = FALSE;
2333 pMac->pmc.pmcState = REQUEST_EXIT_WOWL;
2334 status = pmcSendMessage(pMac, eWNI_PMC_EXIT_WOWL_REQ, NULL, 0);
2335 if ( HAL_STATUS_SUCCESS( status ) )
2336 {
2337 fRemoveCmd = eANI_BOOLEAN_FALSE;
2338 pMac->pmc.requestFullPowerPending = TRUE;
2339 pMac->pmc.requestFullPowerReason = pCommand->u.pmcCmd.fullPowerReason;
2340 }
2341 else
2342 {
2343 smsLog(pMac, LOGP, "PMC: failure to send message eWNI_PMC_EXIT_WOWL_REQ\n");
2344 pmcEnterBmpsState(pMac);
2345 }
2346 }
2347 break;
2348
2349 case eSmeCommandEnterStandby:
2350 if( FULL_POWER == pMac->pmc.pmcState )
2351 {
2352 //Disallow standby if concurrent sessions are present. Note that CSR would have
Jeff Johnsone7245742012-09-05 17:12:55 -07002353 //caused the STA to disconnect the Infra session (if not already disconnected) because of
Jeff Johnson295189b2012-06-20 16:38:30 -07002354 //standby request. But we are now failing the standby request because of concurrent session.
Jeff Johnsone7245742012-09-05 17:12:55 -07002355 //So was the tearing of infra session wasteful if we were going to fail the standby request ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002356 //Not really. This is beacuse if and when BT-AMP etc sessions are torn down we will transition
2357 //to IMPS/standby and still save power.
2358 if (csrIsIBSSStarted(pMac) || csrIsBTAMPStarted(pMac))
2359 {
Jeff Johnsone7245742012-09-05 17:12:55 -07002360 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -07002361 "WLAN: IBSS or BT-AMP session present. Cannot honor standby request");
2362
2363 pmcDoStandbyCallbacks(pMac, eHAL_STATUS_PMC_NOT_NOW);
2364 if(pmcShouldBmpsTimerRun(pMac))
2365 (void)pmcStartTrafficTimer(pMac, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
2366 break;
2367 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002368
Jeff Johnson295189b2012-06-20 16:38:30 -07002369 // Stop traffic timer. Just making sure timer is not running
2370 pmcStopTrafficTimer(pMac);
2371
2372 /* Change state. */
2373 pMac->pmc.pmcState = REQUEST_STANDBY;
2374
2375 /* Tell MAC to have device enter STANDBY mode. We are using the same message
2376 as IMPS mode to avoid code changes in layer below (PE/HAL)*/
2377 status = pmcSendMessage(pMac, eWNI_PMC_ENTER_IMPS_REQ, NULL, 0);
2378 if ( HAL_STATUS_SUCCESS( status ) )
2379 {
2380 //Disable Idle scan in CSR
2381 csrScanSuspendIMPS(pMac);
2382 fRemoveCmd = eANI_BOOLEAN_FALSE;
2383 }
2384 else
2385 {
2386 smsLog(pMac, LOGE, "PMC: failure to send message "
2387 "eWNI_PMC_ENTER_IMPS_REQ\n");
2388 pmcEnterFullPowerState(pMac);
2389 pmcDoStandbyCallbacks(pMac, eHAL_STATUS_FAILURE);
2390 /* Start the timer only if Auto BMPS feature is enabled or an UAPSD session is
2391 required */
2392 if(pmcShouldBmpsTimerRun(pMac))
2393 (void)pmcStartTrafficTimer(pMac, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
2394 }
2395 }
2396 break;
2397
2398 default:
2399 smsLog( pMac, LOGE, FL(" invalid command type %d\n"), pCommand->command );
2400 break;
2401 }
2402
2403 } while( 0 );
2404
2405 return( fRemoveCmd );
2406}
2407
2408eHalStatus pmcEnterImpsCheck( tpAniSirGlobal pMac )
2409{
2410
2411 if( !PMC_IS_READY(pMac) )
2412 {
2413 smsLog(pMac, LOGE, FL("Requesting IMPS when PMC not ready\n"));
Jeff Johnsone7245742012-09-05 17:12:55 -07002414 smsLog(pMac, LOGE, FL("pmcReady = %d pmcState = %s\n"),
Jeff Johnson295189b2012-06-20 16:38:30 -07002415 pMac->pmc.pmcReady, pmcGetPmcStateStr(pMac->pmc.pmcState));
2416 return eHAL_STATUS_FAILURE;
2417 }
2418
2419 /* Check if IMPS is enabled. */
2420 if (!pMac->pmc.impsEnabled)
2421 {
2422 smsLog(pMac, LOG2, FL("IMPS is disabled\n"));
2423 return eHAL_STATUS_PMC_DISABLED;
2424 }
2425
2426 /* Check if IMPS enabled for current power source. */
2427 if ((pMac->pmc.powerSource == AC_POWER) && !pMac->pmc.impsConfig.enterOnAc)
2428 {
2429 smsLog(pMac, LOG2, FL("IMPS is disabled when operating on AC power\n"));
2430 return eHAL_STATUS_PMC_AC_POWER;
2431 }
2432
2433 /* Check that entry into a power save mode is allowed at this time. */
2434 if (!pmcPowerSaveCheck(pMac))
2435 {
2436 smsLog(pMac, LOG2, FL("IMPS cannot be entered now\n"));
2437 return eHAL_STATUS_PMC_NOT_NOW;
2438 }
2439
2440 /* Check that entry into a power save mode is allowed at this time if all
2441 running sessions agree. */
2442 if (!pmcAllowImps(pMac))
2443 {
2444 smsLog(pMac, LOG2, FL("IMPS cannot be entered now\n"));
2445 return eHAL_STATUS_PMC_NOT_NOW;
2446 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002447
Jeff Johnson295189b2012-06-20 16:38:30 -07002448 /* Check if already in IMPS. */
2449 if ((pMac->pmc.pmcState == REQUEST_IMPS) || (pMac->pmc.pmcState == IMPS) ||
2450 (pMac->pmc.pmcState == REQUEST_FULL_POWER))
2451 {
2452 smsLog(pMac, LOG2, FL("Already in IMPS\n"));
2453 return eHAL_STATUS_PMC_ALREADY_IN_IMPS;
2454 }
2455
2456 return ( eHAL_STATUS_SUCCESS );
2457}
2458
2459/* This API detrmines if it is ok to proceed with a Enter BMPS Request or not . Note when
2460 device is in BMPS/UAPSD states, this API returns failure because it is not ok to issue
2461 a BMPS request */
2462eHalStatus pmcEnterBmpsCheck( tpAniSirGlobal pMac )
2463{
2464
2465 /* Check if BMPS is enabled. */
2466 if (!pMac->pmc.bmpsEnabled)
2467 {
2468 smsLog(pMac, LOGE, "PMC: Cannot initiate BMPS. BMPS is disabled\n");
2469 return eHAL_STATUS_PMC_DISABLED;
2470 }
2471
2472 if( !PMC_IS_READY(pMac) )
2473 {
2474 smsLog(pMac, LOGE, FL("Requesting BMPS when PMC not ready\n"));
Jeff Johnsone7245742012-09-05 17:12:55 -07002475 smsLog(pMac, LOGE, FL("pmcReady = %d pmcState = %s\n"),
Jeff Johnson295189b2012-06-20 16:38:30 -07002476 pMac->pmc.pmcReady, pmcGetPmcStateStr(pMac->pmc.pmcState));
2477 return eHAL_STATUS_FAILURE;
2478 }
2479
2480 /* Check that we are associated with a single active session. */
2481 if (!pmcValidateConnectState( pMac ))
2482 {
2483 smsLog(pMac, LOGE, "PMC: STA not associated with an AP with single active session. BMPS cannot be entered\n");
2484 return eHAL_STATUS_FAILURE;
2485 }
2486
2487 /* BMPS can only be requested when device is in Full Power */
2488 if (pMac->pmc.pmcState != FULL_POWER)
2489 {
2490 smsLog(pMac, LOGE, "PMC: Device not in full power. Cannot request BMPS. pmcState %d\n", pMac->pmc.pmcState);
2491 return eHAL_STATUS_FAILURE;
2492 }
2493 /* Check that entry into a power save mode is allowed at this time. */
2494 if (!pmcPowerSaveCheck(pMac))
2495 {
2496 smsLog(pMac, LOGE, "PMC: Power save check failed. BMPS cannot be entered now\n");
2497 return eHAL_STATUS_PMC_NOT_NOW;
2498 }
2499
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07002500 //Remove this code once SLM_Sessionization is supported
2501 //BMPS_WORKAROUND_NOT_NEEDED
2502 if(!IS_FEATURE_SUPPORTED_BY_FW(SLM_SESSIONIZATION))
Mohit Khanna349bc392012-09-11 17:24:52 -07002503 {
2504 smsLog(pMac, LOG1, FL("doBMPSWorkaround %u\n"), pMac->roam.configParam.doBMPSWorkaround);
2505 if (pMac->roam.configParam.doBMPSWorkaround)
2506 {
2507 pMac->roam.configParam.doBMPSWorkaround = 0;
2508 smsLog(pMac, LOG1, FL("reset doBMPSWorkaround to disabled %u\n"), pMac->roam.configParam.doBMPSWorkaround);
2509 csrDisconnectAllActiveSessions(pMac);
2510 smsLog(pMac, LOGE, "PMC: doBMPSWorkaround was enabled. First Disconnect all sessions. pmcState %d\n", pMac->pmc.pmcState);
2511 return eHAL_STATUS_FAILURE;
2512 }
2513 }
2514
Jeff Johnson295189b2012-06-20 16:38:30 -07002515 return ( eHAL_STATUS_SUCCESS );
2516}
2517
2518tANI_BOOLEAN pmcShouldBmpsTimerRun( tpAniSirGlobal pMac )
2519{
Jeff Johnsone7245742012-09-05 17:12:55 -07002520 /* Check if BMPS is enabled and if Auto BMPS Feature is still enabled
Jeff Johnson295189b2012-06-20 16:38:30 -07002521 * or there is a pending Uapsd request or HDD requested BMPS or there
Jeff Johnsone7245742012-09-05 17:12:55 -07002522 * is a pending request for WoWL. In all these cases BMPS is required.
Jeff Johnson295189b2012-06-20 16:38:30 -07002523 * Otherwise just stop the timer and return.
2524 */
Jeff Johnsone7245742012-09-05 17:12:55 -07002525 if (!(pMac->pmc.bmpsEnabled && (pMac->pmc.autoBmpsEntryEnabled ||
Jeff Johnson295189b2012-06-20 16:38:30 -07002526 pMac->pmc.uapsdSessionRequired || pMac->pmc.bmpsRequestedByHdd ||
2527 pMac->pmc.wowlModeRequired )))
2528 {
2529 smsLog(pMac, LOG1, FL("BMPS is not enabled or not required"));
2530 return eANI_BOOLEAN_FALSE;
2531 }
2532
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05302533 if(pMac->pmc.isHostPsEn && pMac->pmc.remainInPowerActiveTillDHCP)
2534 {
2535 smsLog(pMac, LOG1, FL("Host controlled ps enabled and host wants active mode, so dont allow BMPS"));
2536 return eANI_BOOLEAN_FALSE;
2537 }
2538
Jeff Johnsone7245742012-09-05 17:12:55 -07002539 if ((vos_concurrent_sessions_running()) &&
2540 ((csrIsConcurrentInfraConnected( pMac ) ||
2541 (vos_get_concurrency_mode()& VOS_SAP) ||
2542 (vos_get_concurrency_mode()& VOS_P2P_GO))))
2543 {
2544 smsLog(pMac, LOG1, FL("Multiple Sessions/GO/SAP sessions . BMPS should not be started"));
2545 return eANI_BOOLEAN_FALSE;
2546 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002547 /* Check if there is an Infra session. BMPS is possible only if there is
Jeff Johnson295189b2012-06-20 16:38:30 -07002548 * an Infra session */
2549 if (!csrIsInfraConnected(pMac))
2550 {
2551 smsLog(pMac, LOG1, FL("No Infra Session or multiple sessions. BMPS should not be started"));
2552 return eANI_BOOLEAN_FALSE;
2553 }
2554 return eANI_BOOLEAN_TRUE;
2555}
2556
2557
Jeff Johnsone7245742012-09-05 17:12:55 -07002558#ifdef FEATURE_WLAN_DIAG_SUPPORT
Jeff Johnson295189b2012-06-20 16:38:30 -07002559
2560#define PMC_DIAG_EVT_TIMER_INTERVAL ( 5000 )
2561
2562void pmcDiagEvtTimerExpired (tHalHandle hHal)
2563{
2564 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
2565 WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
2566
2567 vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
2568 psRequest.event_subtype = WLAN_PMC_CURRENT_STATE;
2569 psRequest.pmc_current_state = pMac->pmc.pmcState;
2570
2571 WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
2572
2573 smsLog(pMac, LOGW, FL("DIAG event timer expired\n"));
2574
2575 /* re-arm timer */
2576 if (pmcStartDiagEvtTimer(hHal) != eHAL_STATUS_SUCCESS)
2577 {
2578 smsLog(pMac, LOGP, FL("Cannot re-arm DIAG evt timer\n"));
2579 }
2580}
2581
2582eHalStatus pmcStartDiagEvtTimer (tHalHandle hHal)
2583{
2584 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
2585
2586 smsLog(pMac, LOG2, FL("Entering pmcStartDiagEvtTimer\n"));
2587
2588 if (palTimerStart(pMac->hHdd, pMac->pmc.hDiagEvtTimer, PMC_DIAG_EVT_TIMER_INTERVAL *
2589 1000, TRUE) != eHAL_STATUS_SUCCESS)
2590 {
2591 smsLog(pMac, LOGP, FL("Cannot start DIAG evt timer\n"));
2592 return eHAL_STATUS_FAILURE;
2593 }
2594
2595 return eHAL_STATUS_SUCCESS;
2596}
2597
2598void pmcStopDiagEvtTimer (tHalHandle hHal)
2599{
2600 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
2601 smsLog(pMac, LOG2, FL("Entering pmcStopDiagEvtTimer\n"));
2602 (void)palTimerStop(pMac->hHdd, pMac->pmc.hDiagEvtTimer);
2603}
2604#endif