blob: ff9680034ab4003af2d921cd0ec22382c64c8bcd [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
472#if defined(ANI_OS_TYPE_WINDOWS) && !defined(GEN6_ONWARDS)
473 /* In Windows we cannot do this now since we are in DPC context and the message to the
474 SoftMAC to put the device into IMPS will be sent at the end of DPC processing. Instead
475 we set a short timer and start the IMPS exit sequence when the timer fires. */
476 if (palTimerStart(pMac->hHdd, pMac->pmc.hExitPowerSaveTimer, 1000, FALSE) != eHAL_STATUS_SUCCESS)
477 {
478 smsLog(pMac, LOGE, FL("Cannot start exit power save mode timer\n"));
479 PMC_ABORT;
480 return eHAL_STATUS_FAILURE;
481 }
482 return eHAL_STATUS_SUCCESS;
483
484#else
485 /* Start exit IMPS sequence now. */
486 return pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason);
487#endif
488 }
489
490 /* Set timer to come out of IMPS.only if impsPeriod is non-Zero*/
491 if(0 != pMac->pmc.impsPeriod)
492 {
493 if (palTimerStart(pMac->hHdd, pMac->pmc.hImpsTimer, pMac->pmc.impsPeriod * 1000, FALSE) != eHAL_STATUS_SUCCESS)
494 {
495 smsLog(pMac, LOGE, FL("Cannot start IMPS timer\n"));
496 PMC_ABORT;
497 pmcEnterRequestFullPowerState(hHal, eSME_REASON_OTHER);
498 return eHAL_STATUS_FAILURE;
499 }
500 }
501
Jeff Johnsone7245742012-09-05 17:12:55 -0700502 //Vote off RF supplies. Note RF supllies are not voted off if there is a
Jeff Johnson295189b2012-06-20 16:38:30 -0700503 //pending request for full power already
504 status = vos_chipVoteOffRFSupply(&callType, NULL, NULL);
505 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
506
507 status = vos_chipVoteOffXOBuffer(&callType, NULL, NULL);
508 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
509
510 pMac->pmc.rfSuppliesVotedOff= TRUE;
511
512 return eHAL_STATUS_SUCCESS;
513}
514
515
516/******************************************************************************
517*
518* Name: pmcEnterRequestBmpsState
519*
520* Description:
521* Have the device enter the Request BMPS State.
522*
523* Parameters:
524* hHal - HAL handle for device
525*
526* Returns:
527* eHAL_STATUS_SUCCESS - changing state successful
528* eHAL_STATUS_FAILURE - changing state not successful
529*
530******************************************************************************/
531eHalStatus pmcEnterRequestBmpsState (tHalHandle hHal)
532{
533 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
Jeff Johnsone7245742012-09-05 17:12:55 -0700534
Jeff Johnson295189b2012-06-20 16:38:30 -0700535 smsLog(pMac, LOG2, FL("Entering pmcEnterRequestBmpsState\n"));
536
537 /* Can enter Request BMPS State only from Full Power State. */
538 if (pMac->pmc.pmcState != FULL_POWER)
539 {
540 smsLog(pMac, LOGE, FL("Trying to enter Request BMPS State from state %d\n"), pMac->pmc.pmcState);
541 return eHAL_STATUS_FAILURE;
542 }
543
544 /* Stop Traffic timer if running. Note: timer could have expired because of possible
545 race conditions. So no need to check for errors. Just make sure timer is not running */
546 pmcStopTrafficTimer(hHal);
547
548 /* Tell MAC to have device enter BMPS mode. */
549 if ( !pMac->pmc.bmpsRequestQueued )
550 {
551 pMac->pmc.bmpsRequestQueued = eANI_BOOLEAN_TRUE;
552 if(pmcIssueCommand(hHal, eSmeCommandEnterBmps, NULL, 0, FALSE) != eHAL_STATUS_SUCCESS)
553 {
554 smsLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_BMPS_REQ\n");
555 pMac->pmc.bmpsRequestQueued = eANI_BOOLEAN_FALSE;
556 pMac->pmc.pmcState = FULL_POWER;
557 if(pmcShouldBmpsTimerRun(pMac))
558 {
559 (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
560 }
561 return eHAL_STATUS_FAILURE;
562 }
563 }
564 else
565 {
566 smsLog(pMac, LOGE, "PMC: enter BMPS command already queued\n");
567 //restart the timer if needed
568 if(pmcShouldBmpsTimerRun(pMac))
569 {
570 (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
571 }
572 return eHAL_STATUS_SUCCESS;
573 }
574
575 smsLog(pMac, LOGW, FL("eWNI_PMC_ENTER_BMPS_REQ sent to PE\n"));
576
577 return eHAL_STATUS_SUCCESS;
578}
579
580
581/******************************************************************************
582*
583* Name: pmcEnterBmpsState
584*
585* Description:
586* Have the device enter the BMPS State.
587*
588* Parameters:
589* hHal - HAL handle for device
590*
591* Returns:
592* eHAL_STATUS_SUCCESS - changing state successful
593* eHAL_STATUS_FAILURE - changing state not successful
594*
595******************************************************************************/
596eHalStatus pmcEnterBmpsState (tHalHandle hHal)
597{
598 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
599
600 smsLog(pMac, LOG2, FL("Entering pmcEnterBmpsState\n"));
601
602 /* Can enter BMPS State only from 5 states. */
603 if (pMac->pmc.pmcState != REQUEST_BMPS &&
604 pMac->pmc.pmcState != REQUEST_START_UAPSD &&
605 pMac->pmc.pmcState != REQUEST_STOP_UAPSD &&
606 pMac->pmc.pmcState != REQUEST_ENTER_WOWL &&
607 pMac->pmc.pmcState != REQUEST_EXIT_WOWL)
608 {
609 smsLog(pMac, LOGE, FL("Trying to enter BMPS State from state %d\n"), pMac->pmc.pmcState);
610 return eHAL_STATUS_FAILURE;
611 }
612
613 /* Change state. */
614 pMac->pmc.pmcState = BMPS;
615
616 /* Update registerd modules that we are entering BMPS. This is
617 only way to inform modules if PMC entered BMPS power save mode
618 on its own because of traffic timer */
619 pmcDoDeviceStateUpdateCallbacks(hHal, BMPS);
620
621 /* If we have a reqeust for full power pending then we have to go directly into full power. */
622 if (pMac->pmc.requestFullPowerPending)
623 {
624
625#if defined(ANI_OS_TYPE_WINDOWS) && !defined(GEN6_ONWARDS)
626 /* In Windows, we cannot do this now since we are in DPC context and the message to the
627 SoftMAC to put the device into BMPS will be sent at the end of DPC processing. Instead
628 we set a short timer and start the BMPS exit sequence when the timer fires. */
629 if (palTimerStart(pMac->hHdd, pMac->pmc.hExitPowerSaveTimer, 1000, FALSE) != eHAL_STATUS_SUCCESS)
630 {
631 smsLog(pMac, LOGE, FL("Cannot start exit power save mode timer\n"));
632 PMC_ABORT;
633 return eHAL_STATUS_FAILURE;
634 }
635 return eHAL_STATUS_SUCCESS;
636
637#else
638 /* Start exit BMPS sequence now. */
639 smsLog(pMac, LOGW, FL("Pending Full Power request found on entering BMPS mode. "
640 "Start exit BMPS exit sequence\n"));
641 //Note: Reason must have been set when requestFullPowerPending flag was set.
642 pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason);
643 return eHAL_STATUS_SUCCESS;
644#endif
645 }
646
647 /*This should never happen ideally. WOWL and UAPSD not supported at the same time */
648 if (pMac->pmc.wowlModeRequired && pMac->pmc.uapsdSessionRequired)
649 {
650 smsLog(pMac, LOGW, FL("Both UAPSD and WOWL is required on entering BMPS mode. "
651 "UAPSD will be prioritized over WOWL\n"));
652 }
653
654 /* Do we need Uapsd?*/
655 if (pMac->pmc.uapsdSessionRequired)
656 {
657 smsLog(pMac, LOGW, FL("UAPSD session is required on entering BMPS mode. "
658 "Start UAPSD entry sequence\n"));
659 pmcEnterRequestStartUapsdState(hHal);
660 return eHAL_STATUS_SUCCESS;
661 }
662
663 /* Do we need WOWL?*/
664 if (pMac->pmc.wowlModeRequired)
665 {
666 smsLog(pMac, LOGW, FL("WOWL is required on entering BMPS mode. "
667 "Start WOWL entry sequence\n"));
668 pmcRequestEnterWowlState(hHal, &(pMac->pmc.wowlEnterParams));
669 }
670
671 return eHAL_STATUS_SUCCESS;
672}
673
674
675/******************************************************************************
676*
677* Name: pmcPowerSaveCheck
678*
679* Description:
680* Check if device is allowed to enter a power save mode.
681*
682* Parameters:
683* hHal - HAL handle for device
684*
685* Returns:
686* TRUE - entry is allowed
687* FALSE - entry is not allowed at this time
688*
689******************************************************************************/
690tANI_BOOLEAN pmcPowerSaveCheck (tHalHandle hHal)
691{
692 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
693 tListElem *pEntry;
694 tpPowerSaveCheckEntry pPowerSaveCheckEntry;
695 tANI_BOOLEAN (*checkRoutine) (void *checkContext);
696 tANI_BOOLEAN bResult=FALSE;
697
698 smsLog(pMac, LOG2, FL("Entering pmcPowerSaveCheck\n"));
699
700 /* Call the routines in the power save check routine list. If any
701 return FALSE, then we cannot go into power save mode. */
702 pEntry = csrLLPeekHead(&pMac->pmc.powerSaveCheckList, FALSE);
703 while (pEntry != NULL)
704 {
705 pPowerSaveCheckEntry = GET_BASE_ADDR(pEntry, tPowerSaveCheckEntry, link);
706 checkRoutine = pPowerSaveCheckEntry->checkRoutine;
707
708 /* If the checkRoutine is NULL for a paricular entry, proceed with other entries
709 * in the list */
710 if (NULL != checkRoutine)
711 {
712 if (!checkRoutine(pPowerSaveCheckEntry->checkContext))
713 {
714 smsLog(pMac, LOGE, FL("pmcPowerSaveCheck fail!\n"));
Jeff Johnsone7245742012-09-05 17:12:55 -0700715 bResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700716 break;
717 }
718 else
719 {
720 bResult = TRUE;
721 }
722 }
723 pEntry = csrLLNext(&pMac->pmc.powerSaveCheckList, pEntry, FALSE);
724 }
725
726 return bResult;
727}
728
729
730/******************************************************************************
731*
732* Name: pmcSendPowerSaveConfigMessage
733*
734* Description:
735* Send a message to PE/MAC to configure the power saving modes.
736*
737* Parameters:
738* hHal - HAL handle for device
739*
740* Returns:
741* eHAL_STATUS_SUCCESS - message successfuly sent
742* eHAL_STATUS_FAILURE - error while sending message
743*
744******************************************************************************/
745eHalStatus pmcSendPowerSaveConfigMessage (tHalHandle hHal)
746{
747 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
748 tSirPowerSaveCfg powerSaveConfig;
749
750 smsLog(pMac, LOG2, FL("Entering pmcSendPowerSaveConfigMessage\n"));
Jeff Johnsone7245742012-09-05 17:12:55 -0700751
Jeff Johnson295189b2012-06-20 16:38:30 -0700752 palZeroMemory(pMac->hHdd, &(powerSaveConfig), sizeof(tSirPowerSaveCfg));
753
754 switch (pMac->pmc.bmpsConfig.forwardBeacons)
755 {
756 case ePMC_NO_BEACONS:
757 powerSaveConfig.beaconFwd = ePM_BEACON_FWD_NONE;
758 break;
759 case ePMC_BEACONS_WITH_TIM_SET:
760 powerSaveConfig.beaconFwd = ePM_BEACON_FWD_TIM;
761 break;
762 case ePMC_BEACONS_WITH_DTIM_SET:
763 powerSaveConfig.beaconFwd = ePM_BEACON_FWD_DTIM;
764 break;
765 case ePMC_NTH_BEACON:
766 powerSaveConfig.beaconFwd = ePM_BEACON_FWD_NTH;
767 powerSaveConfig.nthBeaconFwd = (tANI_U16)pMac->pmc.bmpsConfig.valueOfN;
768 break;
769 case ePMC_ALL_BEACONS:
770 powerSaveConfig.beaconFwd = ePM_BEACON_FWD_NTH;
771 powerSaveConfig.nthBeaconFwd = 1;
772 break;
773 }
774 powerSaveConfig.fEnablePwrSaveImmediately = pMac->pmc.bmpsConfig.setPmOnLastFrame;
775 powerSaveConfig.fPSPoll = pMac->pmc.bmpsConfig.usePsPoll;
Jeff Johnsone7245742012-09-05 17:12:55 -0700776 powerSaveConfig.fEnableBeaconEarlyTermination =
Jeff Johnson295189b2012-06-20 16:38:30 -0700777 pMac->pmc.bmpsConfig.enableBeaconEarlyTermination;
Jeff Johnsone7245742012-09-05 17:12:55 -0700778 powerSaveConfig.bcnEarlyTermWakeInterval =
Jeff Johnson295189b2012-06-20 16:38:30 -0700779 pMac->pmc.bmpsConfig.bcnEarlyTermWakeInterval;
780
Jeff Johnsone7245742012-09-05 17:12:55 -0700781 /* setcfg for listenInterval. Make sure CFG is updated because PE reads this
Jeff Johnson295189b2012-06-20 16:38:30 -0700782 from CFG at the time of assoc or reassoc */
Jeff Johnsone7245742012-09-05 17:12:55 -0700783 ccmCfgSetInt(pMac, WNI_CFG_LISTEN_INTERVAL, pMac->pmc.bmpsConfig.bmpsPeriod,
Jeff Johnson295189b2012-06-20 16:38:30 -0700784 NULL, eANI_BOOLEAN_FALSE);
785
786 if( pMac->pmc.pmcState == IMPS || pMac->pmc.pmcState == REQUEST_IMPS )
787 {
788 //Wake up the chip first
Jeff Johnsone7245742012-09-05 17:12:55 -0700789 eHalStatus status = pmcDeferMsg( pMac, eWNI_PMC_PWR_SAVE_CFG,
Jeff Johnson295189b2012-06-20 16:38:30 -0700790 &powerSaveConfig, sizeof(tSirPowerSaveCfg) );
791
792 if( eHAL_STATUS_PMC_PENDING == status )
793 {
794 return eHAL_STATUS_SUCCESS;
795 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700796 else
Jeff Johnson295189b2012-06-20 16:38:30 -0700797 {
798 //either fail or already in full power
799 if( !HAL_STATUS_SUCCESS( status ) )
800 {
801 return ( status );
802 }
803 //else let it through because it is in full power state
804 }
805 }
806 /* Send a message so that FW System config is also updated and is in sync with
807 the CFG.*/
Jeff Johnsone7245742012-09-05 17:12:55 -0700808 if (pmcSendMessage(hHal, eWNI_PMC_PWR_SAVE_CFG, &powerSaveConfig, sizeof(tSirPowerSaveCfg))
Jeff Johnson295189b2012-06-20 16:38:30 -0700809 != eHAL_STATUS_SUCCESS)
810 {
811 smsLog(pMac, LOGE, FL("Send of eWNI_PMC_PWR_SAVE_CFG to PE failed\n"));
812 return eHAL_STATUS_FAILURE;
813 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700814
Jeff Johnson295189b2012-06-20 16:38:30 -0700815 return eHAL_STATUS_SUCCESS;
816}
817
818
819/******************************************************************************
820*
821* Name: pmcSendMessage
822*
823* Description:
824* Send a message to PE/MAC.
825*
826* Parameters:
827* hHal - HAL handle for device
828* messageType - message type to send
829* pMessageData - pointer to message data
830* messageSize - Size of the message data
831*
832* Returns:
833* eHAL_STATUS_SUCCESS - message successfuly sent
834* eHAL_STATUS_FAILURE - error while sending message
835*
836******************************************************************************/
837eHalStatus pmcSendMessage (tpAniSirGlobal pMac, tANI_U16 messageType, void *pMessageData, tANI_U32 messageSize)
838{
839 tSirMbMsg *pMsg;
840
841 smsLog(pMac, LOG2, FL("Entering pmcSendMessage, message type %d\n"), messageType);
842
843 /* Allocate and fill in message. */
844 if (palAllocateMemory(pMac->hHdd, (void **)&pMsg, WNI_CFG_MB_HDR_LEN + messageSize) != eHAL_STATUS_SUCCESS)
845 {
846 smsLog(pMac, LOGE, FL("Cannot allocate memory for message\n"));
847 PMC_ABORT;
848 return eHAL_STATUS_FAILURE;
849 }
850 pMsg->type = messageType;
851 pMsg->msgLen = (tANI_U16) (WNI_CFG_MB_HDR_LEN + messageSize);
852 if (messageSize > 0)
853 {
854 if (palCopyMemory(pMac->hHdd, pMsg->data, pMessageData, messageSize) != eHAL_STATUS_SUCCESS)
855 {
856 smsLog(pMac, LOGE, FL("Cannot copy message data\n"));
857 PMC_ABORT;
858 return eHAL_STATUS_FAILURE;
859 }
860 }
861
862 /* Send message. */
863 if (palSendMBMessage(pMac->hHdd, pMsg) != eHAL_STATUS_SUCCESS)
864 {
865 smsLog(pMac, LOGE, FL("Cannot send message\n"));
866 PMC_ABORT;
867 return eHAL_STATUS_FAILURE;
868 }
869
870 return eHAL_STATUS_SUCCESS;
871}
872
873
874/******************************************************************************
875*
876* Name: pmcDoCallbacks
877*
878* Description:
879* Call the IMPS callback routine and the routines in the request full
880* power callback routine list.
881*
882* Parameters:
883* hHal - HAL handle for device
884* callbackStatus - status to pass to the callback routines
885*
886* Returns:
887* nothing
888*
889******************************************************************************/
890void pmcDoCallbacks (tHalHandle hHal, eHalStatus callbackStatus)
891{
892 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
893 tListElem *pEntry;
894 tpRequestFullPowerEntry pRequestFullPowerEntry;
895
896 smsLog(pMac, LOG2, FL("Entering pmcDoCallbacks\n"));
897
898 /* Call IMPS callback routine. */
899 if (pMac->pmc.impsCallbackRoutine != NULL)
900 {
901 pMac->pmc.impsCallbackRoutine(pMac->pmc.impsCallbackContext, callbackStatus);
902 pMac->pmc.impsCallbackRoutine = NULL;
903 }
904
905 /* Call the routines in the request full power callback routine list. */
906 while (NULL != (pEntry = csrLLRemoveHead(&pMac->pmc.requestFullPowerList, TRUE)))
907 {
908 pRequestFullPowerEntry = GET_BASE_ADDR(pEntry, tRequestFullPowerEntry, link);
909 if (pRequestFullPowerEntry->callbackRoutine)
910 pRequestFullPowerEntry->callbackRoutine(pRequestFullPowerEntry->callbackContext, callbackStatus);
911 if (palFreeMemory(pMac->hHdd, pRequestFullPowerEntry) != eHAL_STATUS_SUCCESS)
912 {
913 smsLog(pMac, LOGE, FL("Cannot free request full power routine list entry\n"));
914 PMC_ABORT;
915 }
916 }
917
918}
919
920
921/******************************************************************************
922*
923* Name: pmcStartTrafficTimer
924*
925* Description:
926* Start the timer used in Full Power State to measure traffic
927* levels and determine when to enter BMPS.
928*
929* Parameters:
930* hHal - HAL handle for device
931*
932* Returns:
933* eHAL_STATUS_SUCCESS - timer successfuly started
934* eHAL_STATUS_FAILURE - error while starting timer
935*
936******************************************************************************/
937eHalStatus pmcStartTrafficTimer (tHalHandle hHal, tANI_U32 expirationTime)
938{
939 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
940 VOS_STATUS vosStatus;
941
942 smsLog(pMac, LOG2, FL("Entering pmcStartTrafficTimer\n"));
943
944 vosStatus = vos_timer_start(&pMac->pmc.hTrafficTimer, expirationTime);
945 if ( !VOS_IS_STATUS_SUCCESS(vosStatus) )
946 {
947 if( VOS_STATUS_E_ALREADY == vosStatus )
948 {
949 //Consider this ok since the timer is already started.
950 smsLog(pMac, LOGW, FL(" traffic timer is already started\n"));
951 }
952 else
953 {
954 smsLog(pMac, LOGP, FL("Cannot start traffic timer\n"));
955 return eHAL_STATUS_FAILURE;
956 }
957 }
958
959 return eHAL_STATUS_SUCCESS;
960}
961
962
963/******************************************************************************
964*
965* Name: pmcStopTrafficTimer
966*
967* Description:
968* Cancels the timer (if running) used in Full Power State to measure traffic
969* levels and determine when to enter BMPS.
970*
971* Parameters:
972* hHal - HAL handle for device
973*
974*
975******************************************************************************/
976void pmcStopTrafficTimer (tHalHandle hHal)
977{
978 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
979 smsLog(pMac, LOG2, FL("Entering pmcStopTrafficTimer\n"));
980 vos_timer_stop(&pMac->pmc.hTrafficTimer);
981}
982
983
984/******************************************************************************
985*
986* Name: pmcImpsTimerExpired
987*
988* Description:
989* Called when IMPS timer expires.
990*
991* Parameters:
992* hHal - HAL handle for device
993*
994* Returns:
995* nothing
996*
997******************************************************************************/
998void pmcImpsTimerExpired (tHalHandle hHal)
999{
1000 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1001
1002 smsLog(pMac, LOG2, FL("Entering pmcImpsTimerExpired\n"));
1003
1004 /* If timer expires and we are in a state other than IMPS State then something is wrong. */
1005 if (pMac->pmc.pmcState != IMPS)
1006 {
1007 smsLog(pMac, LOGE, FL("Got IMPS timer expiration in state %d\n"), pMac->pmc.pmcState);
1008 PMC_ABORT;
1009 return;
1010 }
1011
1012 /* Start on the path of going back to full power. */
1013 pmcEnterRequestFullPowerState(hHal, eSME_REASON_OTHER);
1014}
1015
1016
1017/******************************************************************************
1018*
1019* Name: pmcTrafficTimerExpired
1020*
1021* Description:
1022* Called when traffic measurement timer expires.
1023*
1024* Parameters:
1025* hHal - HAL handle for device
1026*
1027* Returns:
1028* nothing
1029*
1030******************************************************************************/
1031void pmcTrafficTimerExpired (tHalHandle hHal)
1032{
1033
1034 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1035 VOS_STATUS vosStatus;
1036
Mohit Khanna23863762012-09-11 17:40:09 -07001037 smsLog(pMac, LOG2, FL("BMPS Traffic timer expired"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001038
1039 /* If timer expires and we are in a state other than Full Power State then something is wrong. */
1040 if (pMac->pmc.pmcState != FULL_POWER)
1041 {
1042 smsLog(pMac, LOGE, FL("Got traffic timer expiration in state %d"), pMac->pmc.pmcState);
1043 return;
1044 }
1045
1046 /* Untill DHCP is not completed remain in power active */
1047 if(pMac->pmc.remainInPowerActiveTillDHCP)
1048 {
Mohit Khanna23863762012-09-11 17:40:09 -07001049 smsLog(pMac, LOG2, FL("BMPS Traffic Timer expired before DHCP completion ignore enter BMPS\n"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001050 pMac->pmc.remainInPowerActiveThreshold++;
1051 if( pMac->pmc.remainInPowerActiveThreshold >= DHCP_REMAIN_POWER_ACTIVE_THRESHOLD)
1052 {
1053 smsLog(pMac, LOGE, FL("Remain in power active DHCP threshold reached FALLBACK to enable enter BMPS\n"));
1054 /*FALLBACK: reset the flag to make BMPS entry possible*/
1055 pMac->pmc.remainInPowerActiveTillDHCP = FALSE;
1056 pMac->pmc.remainInPowerActiveThreshold = 0;
1057 }
1058 //Activate the Traffic Timer again for entering into BMPS
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 re-start traffic timer\n"));
1063 }
1064 return;
1065 }
1066
1067 /* Clear remain in power active threshold */
1068 pMac->pmc.remainInPowerActiveThreshold = 0;
1069
1070 /* Check if the timer should be running */
1071 if (!pmcShouldBmpsTimerRun(pMac))
1072 {
1073 smsLog(pMac, LOGE, FL("BMPS timer should not be running"));
1074 return;
1075 }
1076
Jeff Johnsone7245742012-09-05 17:12:55 -07001077 if (pmcPowerSaveCheck(hHal))
Jeff Johnson295189b2012-06-20 16:38:30 -07001078 {
1079 smsLog(pMac, LOGW, FL("BMPS entry criteria satisfied. Requesting BMPS state"));
Jeff Johnsone7245742012-09-05 17:12:55 -07001080 (void)pmcEnterRequestBmpsState(hHal);
1081 }
1082 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001083 {
1084 /*Some module voted against Power Save. So timer should be restarted again to retry BMPS */
1085 smsLog(pMac, LOGE, FL("Power Save check failed. Retry BMPS again later"));
1086 //Since hTrafficTimer is a vos_timer now, we need to restart the timer here
1087 vosStatus = vos_timer_start(&pMac->pmc.hTrafficTimer, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
1088 if ( !VOS_IS_STATUS_SUCCESS(vosStatus) && (VOS_STATUS_E_ALREADY != vosStatus) )
1089 {
1090 smsLog(pMac, LOGP, FL("Cannot start traffic timer\n"));
1091 return;
1092 }
1093 }
1094}
1095
1096
1097/******************************************************************************
1098*
1099* Name: pmcExitPowerSaveTimerExpired
1100*
1101* Description:
1102* Called when timer used to schedule a deferred power save mode exit expires.
1103*
1104* Parameters:
1105* hHal - HAL handle for device
1106*
1107* Returns:
1108* nothing
1109*
1110******************************************************************************/
1111void pmcExitPowerSaveTimerExpired (tHalHandle hHal)
1112{
1113 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1114
1115 smsLog(pMac, LOG2, FL("Entering pmcExitPowerSaveTimerExpired\n"));
1116
1117 /* Make sure process of exiting power save mode might hasn't already been started due to another trigger. */
1118 if (pMac->pmc.requestFullPowerPending)
1119
1120 /* Start on the path of going back to full power. */
1121 pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason);
1122}
1123
1124/******************************************************************************
1125*
1126* Name: pmcDoBmpsCallbacks
1127*
1128* Description:
1129* Call the registered BMPS callback routines because device is unable to
1130* enter BMPS state
1131*
1132* Parameters:
1133* hHal - HAL handle for device
1134* callbackStatus - Success or Failure.
1135*
1136* Returns:
1137* nothing
1138*
1139******************************************************************************/
1140void pmcDoBmpsCallbacks (tHalHandle hHal, eHalStatus callbackStatus)
1141{
1142 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1143 tListElem *pEntry;
1144 tpRequestBmpsEntry pRequestBmpsEntry;
1145
1146 smsLog(pMac, LOG2, "PMC: entering pmcDoBmpsCallbacks\n");
1147
1148 /* Call the routines in the request BMPS callback routine list. */
1149 pEntry = csrLLRemoveHead(&pMac->pmc.requestBmpsList, FALSE);
1150 while (pEntry != NULL)
1151 {
1152 pRequestBmpsEntry = GET_BASE_ADDR(pEntry, tRequestBmpsEntry, link);
1153 if (pRequestBmpsEntry->callbackRoutine)
1154 pRequestBmpsEntry->callbackRoutine(pRequestBmpsEntry->callbackContext,
1155 callbackStatus);
1156 palFreeMemory(pMac->hHdd, pRequestBmpsEntry);
1157 pEntry = csrLLRemoveHead(&pMac->pmc.requestBmpsList, FALSE);
1158 }
1159}
1160
1161
1162
1163
1164/******************************************************************************
1165*
1166* Name: pmcDoStartUapsdCallbacks
1167*
1168* Description:
1169* Call the registered UAPSD callback routines because device is unable to
1170* start UAPSD state
1171*
1172* Parameters:
1173* hHal - HAL handle for device
Jeff Johnsone7245742012-09-05 17:12:55 -07001174* callbackStatus - Success or Failure.
Jeff Johnson295189b2012-06-20 16:38:30 -07001175*
1176* Returns:
1177* nothing
1178*
1179******************************************************************************/
1180void pmcDoStartUapsdCallbacks (tHalHandle hHal, eHalStatus callbackStatus)
1181{
1182 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1183 tListElem *pEntry;
1184 tpStartUapsdEntry pStartUapsdEntry;
1185
1186 smsLog(pMac, LOG2, "PMC: entering pmcDoStartUapsdCallbacks\n");
1187
1188 /* Call the routines in the request start UAPSD callback routine list. */
1189 pEntry = csrLLRemoveHead(&pMac->pmc.requestStartUapsdList, FALSE);
1190 while (pEntry != NULL)
1191 {
1192 pStartUapsdEntry = GET_BASE_ADDR(pEntry, tStartUapsdEntry, link);
1193 pStartUapsdEntry->callbackRoutine(pStartUapsdEntry->callbackContext,
1194 callbackStatus);
1195 palFreeMemory(pMac->hHdd, pStartUapsdEntry);
1196 pEntry = csrLLRemoveHead(&pMac->pmc.requestStartUapsdList, FALSE);
1197 }
1198}
1199
1200/******************************************************************************
1201*
1202* Name: pmcEnterRequestStartUapsdState
1203*
1204* Description:
1205* Have the device enter the UAPSD State.
1206*
1207* Parameters:
1208* hHal - HAL handle for device
1209*
1210* Returns:
1211* eHAL_STATUS_SUCCESS - changing state successful
1212* eHAL_STATUS_FAILURE - changing state not successful
1213*
1214******************************************************************************/
1215eHalStatus pmcEnterRequestStartUapsdState (tHalHandle hHal)
1216{
1217 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1218 v_BOOL_t fFullPower = VOS_FALSE; //need to get back to full power state
1219
1220 smsLog(pMac, LOG2, "PMC: entering pmcEnterRequestStartUapsdState\n");
1221
1222 /* Can enter UAPSD State only from FULL_POWER or BMPS State. */
1223 switch (pMac->pmc.pmcState)
1224 {
1225 case FULL_POWER:
1226 /* Check that entry into a power save mode is allowed at this time. */
1227 if (!pmcPowerSaveCheck(hHal))
1228 {
1229 smsLog(pMac, LOGW, "PMC: Power save check failed. UAPSD request "
1230 "will be accepted and buffered\n");
1231 /* UAPSD mode will be attempted when we enter BMPS later */
1232 pMac->pmc.uapsdSessionRequired = TRUE;
1233 /* Make sure the BMPS retry timer is running */
1234 if(pmcShouldBmpsTimerRun(pMac))
1235 (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
1236 break;
1237 }
1238 else
1239 {
1240 pMac->pmc.uapsdSessionRequired = TRUE;
1241 //Check BTC state
1242#ifndef WLAN_MDM_CODE_REDUCTION_OPT
1243 if( btcIsReadyForUapsd( pMac ) )
1244#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
1245 {
1246 /* Put device in BMPS mode first. This step should NEVER fail.
1247 That is why no need to buffer the UAPSD request*/
1248 if(pmcEnterRequestBmpsState(hHal) != eHAL_STATUS_SUCCESS)
1249 {
1250 smsLog(pMac, LOGE, "PMC: Device in Full Power. Enter Request Bmps failed. "
1251 "UAPSD request will be dropped \n");
1252 return eHAL_STATUS_FAILURE;
1253 }
1254 }
1255#ifndef WLAN_MDM_CODE_REDUCTION_OPT
1256 else
1257 {
1258 (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
1259 }
1260#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
1261 }
1262 break;
1263
1264 case BMPS:
1265 //It is already in BMPS mode, check BTC state
1266#ifndef WLAN_MDM_CODE_REDUCTION_OPT
1267 if( btcIsReadyForUapsd(pMac) )
1268#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
1269 {
1270 /* Tell MAC to have device enter UAPSD mode. */
1271 if (pmcIssueCommand(hHal, eSmeCommandEnterUapsd, NULL, 0, FALSE) !=
1272 eHAL_STATUS_SUCCESS)
1273 {
1274 smsLog(pMac, LOGE, "PMC: failure to send message "
1275 "eWNI_PMC_ENTER_BMPS_REQ\n");
1276 return eHAL_STATUS_FAILURE;
1277 }
1278 }
1279#ifndef WLAN_MDM_CODE_REDUCTION_OPT
1280 else
1281 {
1282 //Not ready for UAPSD at this time, save it first and wake up the chip
1283 smsLog(pMac, LOGE, " PMC state = %d\n",pMac->pmc.pmcState);
1284 pMac->pmc.uapsdSessionRequired = TRUE;
Jeff Johnsone7245742012-09-05 17:12:55 -07001285 /* While BTC traffic is going on, STA can be in BMPS
Jeff Johnson295189b2012-06-20 16:38:30 -07001286 * and need not go to Full Power */
Jeff Johnsone7245742012-09-05 17:12:55 -07001287 //fFullPower = VOS_TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001288 }
1289#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
1290 break;
1291
1292 case REQUEST_START_UAPSD:
1293#ifndef WLAN_MDM_CODE_REDUCTION_OPT
1294 if( !btcIsReadyForUapsd(pMac) )
1295 {
1296 //BTC rejects UAPSD, bring it back to full power
1297 fFullPower = VOS_TRUE;
1298 }
1299#endif
1300 break;
1301
1302 case REQUEST_BMPS:
1303 /* Buffer request for UAPSD mode. */
1304 pMac->pmc.uapsdSessionRequired = TRUE;
1305#ifndef WLAN_MDM_CODE_REDUCTION_OPT
1306 if( !btcIsReadyForUapsd(pMac) )
1307 {
1308 //BTC rejects UAPSD, bring it back to full power
1309 fFullPower = VOS_TRUE;
1310 }
1311#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
1312 break;
1313
1314 default:
1315 smsLog(pMac, LOGE, "PMC: trying to enter UAPSD State from state %d\n",
1316 pMac->pmc.pmcState);
1317 return eHAL_STATUS_FAILURE;
1318 }
1319
1320 if(fFullPower)
1321 {
1322 if( eHAL_STATUS_PMC_PENDING != pmcRequestFullPower( pMac, NULL, NULL, eSME_REASON_OTHER ) )
1323 {
1324 //This is an error
1325 smsLog(pMac, LOGE, FL(" fail to request full power because BTC\n"));
1326 }
1327 }
1328
1329 return eHAL_STATUS_SUCCESS;
1330}
1331
1332/******************************************************************************
1333*
1334* Name: pmcEnterUapsdState
1335*
1336* Description:
1337* Have the device enter the UAPSD State.
1338*
1339* Parameters:
1340* hHal - HAL handle for device
1341*
1342* Returns:
1343* eHAL_STATUS_SUCCESS - changing state successful
1344* eHAL_STATUS_FAILURE - changing state not successful
1345*
1346******************************************************************************/
1347eHalStatus pmcEnterUapsdState (tHalHandle hHal)
1348{
1349 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1350
1351 smsLog(pMac, LOG2, "PMC: entering pmcEnterUapsdState\n");
1352
1353 /* Can enter UAPSD State only from Request UAPSD State. */
1354 if (pMac->pmc.pmcState != REQUEST_START_UAPSD )
1355 {
1356 smsLog(pMac, LOGE, "PMC: trying to enter UAPSD State from state %d\n",
1357 pMac->pmc.pmcState);
1358 return eHAL_STATUS_FAILURE;
1359 }
1360
1361 /* Change state. */
1362 pMac->pmc.pmcState = UAPSD;
1363
1364 /* Update registerd modules that we are entering UAPSD. This is
1365 only way to inform modules if PMC resumed UAPSD power save mode
1366 on its own after full power mode */
1367 pmcDoDeviceStateUpdateCallbacks(hHal, UAPSD);
Jeff Johnsone7245742012-09-05 17:12:55 -07001368
Jeff Johnson295189b2012-06-20 16:38:30 -07001369 /* If we have a reqeust for full power pending then we have to go
1370 directly into full power. */
1371 if (pMac->pmc.requestFullPowerPending)
1372 {
1373 /* Start exit UAPSD sequence now. */
1374 return pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason);
1375 }
1376
1377 return eHAL_STATUS_SUCCESS;
1378}
1379
1380
1381/******************************************************************************
1382*
1383* Name: pmcEnterRequestStopUapsdState
1384*
1385* Description:
1386* Have the device Stop the UAPSD State.
1387*
1388* Parameters:
1389* hHal - HAL handle for device
1390*
1391* Returns:
1392* eHAL_STATUS_SUCCESS - changing state successful
1393* eHAL_STATUS_FAILURE - changing state not successful
1394*
1395******************************************************************************/
1396eHalStatus pmcEnterRequestStopUapsdState (tHalHandle hHal)
1397{
1398 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1399
1400 smsLog(pMac, LOG2, "PMC: entering pmcEnterRequestStopUapsdState\n");
1401
1402 /* If already in REQUEST_STOP_UAPSD, simply return */
1403 if (pMac->pmc.pmcState == REQUEST_STOP_UAPSD)
1404 {
1405 return eHAL_STATUS_SUCCESS;
1406 }
1407
1408 /* Can enter Request Stop UAPSD State only from UAPSD */
1409 if (pMac->pmc.pmcState != UAPSD)
1410 {
1411 smsLog(pMac, LOGE, "PMC: trying to enter Request Stop UAPSD State from "
1412 "state %d\n", pMac->pmc.pmcState);
1413 return eHAL_STATUS_FAILURE;
1414 }
1415
1416 /* Tell MAC to have device exit UAPSD mode. */
1417 if (pmcIssueCommand(hHal, eSmeCommandExitUapsd, NULL, 0, FALSE) !=
1418 eHAL_STATUS_SUCCESS)
1419 {
1420 smsLog(pMac, LOGE, "PMC: failure to send message "
1421 "eWNI_PMC_EXIT_UAPSD_REQ\n");
1422 return eHAL_STATUS_FAILURE;
1423 }
1424
1425 return eHAL_STATUS_SUCCESS;
1426}
1427
1428/******************************************************************************
1429*
1430* Name: pmcEnterRequestStandbyState
1431*
1432* Description:
1433* Have the device enter the Request STANDBY State.
1434*
1435* Parameters:
1436* hHal - HAL handle for device
1437*
1438* Returns:
1439* eHAL_STATUS_SUCCESS - changing state successful
1440* eHAL_STATUS_FAILURE - changing state not successful
1441*
1442******************************************************************************/
1443eHalStatus pmcEnterRequestStandbyState (tHalHandle hHal)
1444{
1445 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1446
1447 smsLog(pMac, LOG2, "PMC: entering pmcEnterRequestStandbyState\n");
1448
1449 /* Can enter Standby State only from Full Power State. */
1450 if (pMac->pmc.pmcState != FULL_POWER)
1451 {
1452 smsLog(pMac, LOGE, "PMC: trying to enter Standby State from "
1453 "state %d\n", pMac->pmc.pmcState);
1454 return eHAL_STATUS_FAILURE;
1455 }
1456
1457 // Stop traffic timer. Just making sure timer is not running
1458 pmcStopTrafficTimer(hHal);
1459
1460 /* Tell MAC to have device enter STANDBY mode. We are using the same message
1461 as IMPS mode to avoid code changes in layer below (PE/HAL)*/
1462 if (pmcIssueCommand(hHal, eSmeCommandEnterStandby, NULL, 0, FALSE) !=
1463 eHAL_STATUS_SUCCESS)
1464 {
1465 smsLog(pMac, LOGE, "PMC: failure to send message "
1466 "eWNI_PMC_ENTER_IMPS_REQ\n");
1467 pMac->pmc.pmcState = FULL_POWER;
1468
1469 if(pmcShouldBmpsTimerRun(pMac))
1470 (void)pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
1471 return eHAL_STATUS_FAILURE;
1472 }
Jeff Johnsone7245742012-09-05 17:12:55 -07001473
Jeff Johnson295189b2012-06-20 16:38:30 -07001474 return eHAL_STATUS_SUCCESS;
1475}
1476
1477/******************************************************************************
1478*
1479* Name: pmcEnterStandbyState
1480*
1481* Description:
1482* Have the device enter the STANDBY State.
1483*
1484* Parameters:
1485* hHal - HAL handle for device
1486*
1487* Returns:
1488* eHAL_STATUS_SUCCESS - changing state successful
1489* eHAL_STATUS_FAILURE - changing state not successful
1490*
1491******************************************************************************/
1492eHalStatus pmcEnterStandbyState (tHalHandle hHal)
1493{
1494 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1495 vos_call_status_type callType;
1496 VOS_STATUS status;
1497
1498 smsLog(pMac, LOG2, "PMC: entering pmcEnterStandbyState\n");
1499
1500 /* Can enter STANDBY State only from REQUEST_STANDBY State. */
1501 if (pMac->pmc.pmcState != REQUEST_STANDBY)
1502 {
1503 smsLog(pMac, LOGE, "PMC: trying to enter STANDBY State from state %d\n",
1504 pMac->pmc.pmcState);
1505 return eHAL_STATUS_FAILURE;
1506 }
1507
1508 /* Change state. */
1509 pMac->pmc.pmcState = STANDBY;
1510
1511 /* If we have a reqeust for full power pending then we have to go
1512 directly into full power. */
1513 if (pMac->pmc.requestFullPowerPending)
1514 {
1515 /* Start exit STANDBY sequence now. */
1516 return pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason);
1517 }
1518
1519 //Note that RF supplies are not voted off if there is already a pending request
1520 //for full power
1521 status = vos_chipVoteOffRFSupply(&callType, NULL, NULL);
1522 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
1523
1524 status = vos_chipVoteOffXOBuffer(&callType, NULL, NULL);
1525 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
1526
1527 pMac->pmc.rfSuppliesVotedOff= TRUE;
1528
1529 return eHAL_STATUS_SUCCESS;
1530}
1531
1532/******************************************************************************
1533*
1534* Name: pmcDoStandbyCallbacks
1535*
1536* Description:
Jeff Johnsone7245742012-09-05 17:12:55 -07001537* Call the registered Standby callback routines
Jeff Johnson295189b2012-06-20 16:38:30 -07001538*
1539* Parameters:
1540* hHal - HAL handle for device
1541* callbackStatus - Success or Failure.
1542*
1543* Returns:
1544* nothing
1545*
1546******************************************************************************/
1547void pmcDoStandbyCallbacks (tHalHandle hHal, eHalStatus callbackStatus)
1548{
1549 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
Jeff Johnsone7245742012-09-05 17:12:55 -07001550
Jeff Johnson295189b2012-06-20 16:38:30 -07001551 smsLog(pMac, LOG2, "PMC: entering pmcDoStandbyCallbacks\n");
1552
1553 /* Call Standby callback routine. */
1554 if (pMac->pmc.standbyCallbackRoutine != NULL)
1555 pMac->pmc.standbyCallbackRoutine(pMac->pmc.standbyCallbackContext, callbackStatus);
1556 pMac->pmc.standbyCallbackRoutine = NULL;
1557 pMac->pmc.standbyCallbackContext = NULL;
1558}
1559
1560/******************************************************************************
1561*
1562* Name: pmcGetPmcState
1563*
1564* Description:
1565* Return the PMC state
1566*
1567* Parameters:
1568* hHal - HAL handle for device
1569*
1570* Returns:
1571* tPmcState (one of IMPS, REQUEST_IMPS, BMPS, REQUEST_BMPS etc)
1572*
1573******************************************************************************/
1574tPmcState pmcGetPmcState (tHalHandle hHal)
1575{
1576 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
Jeff Johnsone7245742012-09-05 17:12:55 -07001577 return pMac->pmc.pmcState;
Jeff Johnson295189b2012-06-20 16:38:30 -07001578}
1579
1580const char* pmcGetPmcStateStr(tPmcState state)
1581{
1582 switch(state)
1583 {
1584 case STOPPED:
1585 return "STOPPED";
1586 case FULL_POWER:
1587 return "FULL_POWER";
1588 case LOW_POWER:
1589 return "LOW_POWER";
1590 case IMPS:
1591 return "IMPS";
1592 case BMPS:
1593 return "BMPS";
1594 case UAPSD:
1595 return "UAPSD";
1596 case STANDBY:
1597 return "STANDBY";
1598 case REQUEST_IMPS:
1599 return "REQUEST_IMPS";
1600 case REQUEST_BMPS:
1601 return "REQUEST_BMPS";
1602 case REQUEST_START_UAPSD:
1603 return "REQUEST_START_UAPSD";
1604 case REQUEST_STOP_UAPSD:
1605 return "REQUEST_STOP_UAPSD";
1606 case REQUEST_FULL_POWER:
1607 return "REQUEST_FULL_POWER";
1608 case REQUEST_STANDBY:
1609 return "REQUEST_STANDBY";
1610 case REQUEST_ENTER_WOWL:
1611 return "REQUEST_ENTER_WOWL";
1612 case REQUEST_EXIT_WOWL:
1613 return "REQUEST_EXIT_WOWL";
1614 case WOWL:
1615 return "WOWL";
1616 default:
1617 break;
1618 }
1619
1620 return "UNKNOWN";
1621}
1622
1623void pmcDoDeviceStateUpdateCallbacks (tHalHandle hHal, tPmcState state)
1624{
1625 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1626 tListElem *pEntry;
1627 tpDeviceStateUpdateIndEntry pDeviceStateUpdateIndEntry;
1628 void (*callbackRoutine) (void *callbackContext, tPmcState pmcState);
1629
1630 smsLog(pMac, LOG2, FL("PMC - Update registered modules of new device "
1631 "state: %s\n"), pmcGetPmcStateStr(state));
1632
1633 /* Call the routines in the update device state routine list. */
1634 pEntry = csrLLPeekHead(&pMac->pmc.deviceStateUpdateIndList, FALSE);
1635 while (pEntry != NULL)
1636 {
1637 pDeviceStateUpdateIndEntry = GET_BASE_ADDR(pEntry, tDeviceStateUpdateIndEntry, link);
1638 callbackRoutine = pDeviceStateUpdateIndEntry->callbackRoutine;
1639 callbackRoutine(pDeviceStateUpdateIndEntry->callbackContext, state);
1640 pEntry = csrLLNext(&pMac->pmc.deviceStateUpdateIndList, pEntry, FALSE);
1641 }
1642}
1643
1644/******************************************************************************
1645*
1646* Name: pmcRequestEnterWowlState
1647*
1648* Description:
1649* Have the device enter the WOWL State.
1650*
1651* Parameters:
1652* hHal - HAL handle for device
1653*
1654* Returns:
1655* eHAL_STATUS_SUCCESS - WOWL mode will be entered
1656* eHAL_STATUS_FAILURE - WOWL mode cannot be entered
1657*
1658******************************************************************************/
1659eHalStatus pmcRequestEnterWowlState(tHalHandle hHal, tpSirSmeWowlEnterParams wowlEnterParams)
1660{
1661 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1662 smsLog(pMac, LOG2, "PMC: entering pmcRequestEnterWowlState\n");
1663
1664 switch (pMac->pmc.pmcState)
1665 {
1666 case FULL_POWER:
1667 /* Put device in BMPS mode first. This step should NEVER fail. */
1668 if(pmcEnterRequestBmpsState(hHal) != eHAL_STATUS_SUCCESS)
1669 {
1670 smsLog(pMac, LOGE, "PMC: Device in Full Power. pmcEnterRequestBmpsState failed. "
1671 "Cannot enter WOWL\n");
1672 return eHAL_STATUS_FAILURE;
1673 }
1674 break;
1675
1676 case REQUEST_BMPS:
1677 smsLog(pMac, LOGW, "PMC: BMPS transaction going on. WOWL request "
Jeff Johnsone7245742012-09-05 17:12:55 -07001678 "will be buffered\n");
Jeff Johnson295189b2012-06-20 16:38:30 -07001679 break;
1680
1681 case BMPS:
1682 case WOWL:
1683 /* Tell MAC to have device enter WOWL mode. Note: We accept WOWL request
1684 when we are in WOWL mode. This allows HDD to change WOWL configuration
1685 without having to exit WOWL mode */
1686 if (pmcIssueCommand(hHal, eSmeCommandEnterWowl, wowlEnterParams, sizeof(tSirSmeWowlEnterParams), FALSE) !=
1687 eHAL_STATUS_SUCCESS)
1688 {
1689 smsLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_WOWL_REQ\n");
1690 return eHAL_STATUS_FAILURE;
1691 }
1692 break;
1693
1694 case REQUEST_ENTER_WOWL:
1695 //Multiple enter WOWL requests at the same time are not accepted
1696 smsLog(pMac, LOGE, "PMC: Enter WOWL transaction already going on. New WOWL request "
1697 "will be rejected\n");
1698 return eHAL_STATUS_FAILURE;
1699
1700 case REQUEST_EXIT_WOWL:
1701 smsLog(pMac, LOGW, "PMC: Exit WOWL transaction going on. New WOWL request "
Jeff Johnsone7245742012-09-05 17:12:55 -07001702 "will be buffered\n");
Jeff Johnson295189b2012-06-20 16:38:30 -07001703 break;
1704
1705 default:
1706 smsLog(pMac, LOGE, "PMC: Trying to enter WOWL State from state %s\n",
1707 pmcGetPmcStateStr(pMac->pmc.pmcState));
1708 return eHAL_STATUS_FAILURE;
1709 }
1710
1711 return eHAL_STATUS_SUCCESS;
1712}
1713
1714/******************************************************************************
1715*
1716* Name: pmcEnterWowlState
1717*
1718* Description:
1719* Have the device enter the WOWL State.
1720*
1721* Parameters:
1722* hHal - HAL handle for device
1723*
1724* Returns:
1725* eHAL_STATUS_SUCCESS - changing state successful
1726* eHAL_STATUS_FAILURE - changing state not successful
1727*
1728******************************************************************************/
1729eHalStatus pmcEnterWowlState (tHalHandle hHal)
1730{
1731 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1732
1733 smsLog(pMac, LOG2, "PMC: entering pmcEnterWowlState\n");
1734
1735 /* Can enter WOWL State only from Request WOWL State. */
1736 if (pMac->pmc.pmcState != REQUEST_ENTER_WOWL )
1737 {
1738 smsLog(pMac, LOGP, "PMC: trying to enter WOWL State from state %d\n",
1739 pMac->pmc.pmcState);
1740 return eHAL_STATUS_FAILURE;
1741 }
1742
1743 /* Change state. */
1744 pMac->pmc.pmcState = WOWL;
1745
1746 /* Clear the buffered command for WOWL */
1747 pMac->pmc.wowlModeRequired = FALSE;
1748
1749 /* If we have a reqeust for full power pending then we have to go
1750 directly into full power. */
1751 if (pMac->pmc.requestFullPowerPending)
1752 {
1753 /* Start exit Wowl sequence now. */
1754 return pmcEnterRequestFullPowerState(hHal, pMac->pmc.requestFullPowerReason);
1755 }
1756
1757 return eHAL_STATUS_SUCCESS;
1758}
1759
1760/******************************************************************************
1761*
1762* Name: pmcRequestExitWowlState
1763*
1764* Description:
1765* Have the device exit WOWL State.
1766*
1767* Parameters:
1768* hHal - HAL handle for device
1769*
1770* Returns:
1771* eHAL_STATUS_SUCCESS - Exit WOWL successful
1772* eHAL_STATUS_FAILURE - Exit WOWL unsuccessful
1773*
1774******************************************************************************/
1775eHalStatus pmcRequestExitWowlState(tHalHandle hHal)
1776{
1777 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1778
1779 smsLog(pMac, LOG2, "PMC: entering pmcRequestExitWowlState\n");
1780
1781 switch (pMac->pmc.pmcState)
1782 {
1783 case WOWL:
1784 /* Tell MAC to have device exit WOWL mode. */
1785 if (pmcIssueCommand(hHal, eSmeCommandExitWowl, NULL, 0, FALSE) !=
1786 eHAL_STATUS_SUCCESS)
1787 {
1788 smsLog(pMac, LOGP, "PMC: failure to send message eWNI_PMC_EXIT_WOWL_REQ\n");
1789 return eHAL_STATUS_FAILURE;
1790 }
1791 break;
1792
1793 case REQUEST_ENTER_WOWL:
1794 smsLog(pMac, LOGP, "PMC: Rcvd exit WOWL even before enter WOWL was completed\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07001795 return eHAL_STATUS_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001796
1797 default:
1798 smsLog(pMac, LOGW, "PMC: Got exit WOWL in state %s. Nothing to do as already out of WOWL\n",
1799 pmcGetPmcStateStr(pMac->pmc.pmcState));
1800 break;
1801 }
1802
1803 return eHAL_STATUS_SUCCESS;
1804}
1805
1806/******************************************************************************
1807*
1808* Name: pmcDoEnterWowlCallbacks
1809*
1810* Description:
1811* Invoke Enter WOWL callbacks
1812*
1813* Parameters:
1814* hHal - HAL handle for device
1815*
1816* Returns: None
1817*
1818******************************************************************************/
1819void pmcDoEnterWowlCallbacks (tHalHandle hHal, eHalStatus callbackStatus)
1820{
1821 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
Jeff Johnsone7245742012-09-05 17:12:55 -07001822
Jeff Johnson295189b2012-06-20 16:38:30 -07001823 smsLog(pMac, LOG2, "PMC: entering pmcDoWowlCallbacks\n");
1824
1825 /* Call Wowl callback routine. */
1826 if (pMac->pmc.enterWowlCallbackRoutine != NULL)
1827 pMac->pmc.enterWowlCallbackRoutine(pMac->pmc.enterWowlCallbackContext, callbackStatus);
1828
1829 pMac->pmc.enterWowlCallbackRoutine = NULL;
1830 pMac->pmc.enterWowlCallbackContext = NULL;
1831}
1832
1833
1834static void pmcProcessDeferredMsg( tpAniSirGlobal pMac )
1835{
1836 tPmcDeferredMsg *pDeferredMsg;
1837 tListElem *pEntry;
1838
1839 while( NULL != ( pEntry = csrLLRemoveHead( &pMac->pmc.deferredMsgList, eANI_BOOLEAN_TRUE ) ) )
1840 {
1841 pDeferredMsg = GET_BASE_ADDR( pEntry, tPmcDeferredMsg, link );
1842 switch (pDeferredMsg->messageType)
1843 {
1844 case eWNI_PMC_WOWL_ADD_BCAST_PTRN:
1845 VOS_ASSERT( pDeferredMsg->size == sizeof(tSirWowlAddBcastPtrn) );
Jeff Johnsone7245742012-09-05 17:12:55 -07001846 if (pmcSendMessage(pMac, eWNI_PMC_WOWL_ADD_BCAST_PTRN,
Jeff Johnson295189b2012-06-20 16:38:30 -07001847 &pDeferredMsg->u.wowlAddPattern, sizeof(tSirWowlAddBcastPtrn))
1848 != eHAL_STATUS_SUCCESS)
1849 {
1850 smsLog(pMac, LOGE, FL("Send of eWNI_PMC_WOWL_ADD_BCAST_PTRN to PE failed\n"));
1851 }
1852 break;
1853
1854 case eWNI_PMC_WOWL_DEL_BCAST_PTRN:
1855 VOS_ASSERT( pDeferredMsg->size == sizeof(tSirWowlDelBcastPtrn) );
Jeff Johnsone7245742012-09-05 17:12:55 -07001856 if (pmcSendMessage(pMac, eWNI_PMC_WOWL_DEL_BCAST_PTRN,
Jeff Johnson295189b2012-06-20 16:38:30 -07001857 &pDeferredMsg->u.wowlDelPattern, sizeof(tSirWowlDelBcastPtrn))
1858 != eHAL_STATUS_SUCCESS)
1859 {
1860 smsLog(pMac, LOGE, FL("Send of eWNI_PMC_WOWL_ADD_BCAST_PTRN to PE failed\n"));
1861 }
1862 break;
1863
1864 case eWNI_PMC_PWR_SAVE_CFG:
1865 VOS_ASSERT( pDeferredMsg->size == sizeof(tSirPowerSaveCfg) );
Jeff Johnsone7245742012-09-05 17:12:55 -07001866 if (pmcSendMessage(pMac, eWNI_PMC_PWR_SAVE_CFG,
1867 &pDeferredMsg->u.powerSaveConfig, sizeof(tSirPowerSaveCfg))
Jeff Johnson295189b2012-06-20 16:38:30 -07001868 != eHAL_STATUS_SUCCESS)
1869 {
1870 smsLog(pMac, LOGE, FL("Send of eWNI_PMC_PWR_SAVE_CFG to PE failed\n"));
1871 }
1872 break;
1873
1874 default:
1875 smsLog(pMac, LOGE, FL("unknown message (%d)\n"), pDeferredMsg->messageType);
1876 break;
1877 }
1878 //Need to free the memory here
1879 palFreeMemory( pMac->hHdd, pDeferredMsg );
1880 } //while
1881}
1882
1883
1884eHalStatus pmcDeferMsg( tpAniSirGlobal pMac, tANI_U16 messageType, void *pData, tANI_U32 size)
1885{
1886 tPmcDeferredMsg *pDeferredMsg;
1887 eHalStatus status;
1888
1889 if( !HAL_STATUS_SUCCESS( palAllocateMemory( pMac->hHdd, (void **)&pDeferredMsg, sizeof(tPmcDeferredMsg) ) ) )
1890 {
1891 smsLog(pMac, LOGE, FL("Cannot allocate memory for callback context\n"));
1892 return eHAL_STATUS_RESOURCES;
1893 }
1894 palZeroMemory( pMac->hHdd, pDeferredMsg, sizeof(tPmcDeferredMsg) );
1895 pDeferredMsg->messageType = messageType;
1896 pDeferredMsg->size = (tANI_U16)size;
1897 if( pData )
1898 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001899 if( !HAL_STATUS_SUCCESS( palCopyMemory( pMac->hHdd, &pDeferredMsg->u.data,
Jeff Johnson295189b2012-06-20 16:38:30 -07001900 pData, size ) ) )
1901 {
1902 smsLog(pMac, LOGE, FL("Cannot copy pattern for callback context\n"));
1903 palFreeMemory( pMac->hHdd, pDeferredMsg );
1904 return eHAL_STATUS_FAILURE;
1905 }
1906 }
1907 csrLLInsertTail( &pMac->pmc.deferredMsgList, &pDeferredMsg->link, eANI_BOOLEAN_TRUE );
Jeff Johnsone7245742012-09-05 17:12:55 -07001908 //No callback is needed. The messages are put into deferred queue and be processed first
Jeff Johnson295189b2012-06-20 16:38:30 -07001909 //when enter full power is complete.
1910 status = pmcRequestFullPower( pMac, NULL, NULL, eSME_REASON_OTHER );
1911 if( eHAL_STATUS_PMC_PENDING != status )
1912 {
1913 //either fail or already in full power
1914 if( csrLLRemoveEntry( &pMac->pmc.deferredMsgList, &pDeferredMsg->link, eANI_BOOLEAN_TRUE ) )
1915 {
1916 palFreeMemory( pMac->hHdd, pDeferredMsg );
1917 }
1918 if( !HAL_STATUS_SUCCESS( status ) )
1919 {
1920 smsLog(pMac, LOGE, FL("failed to request full power status = %d\n"), status);
1921 }
1922 }
1923
1924 return (status);
1925}
1926
1927void pmcReleaseCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand )
1928{
1929 if(!pCommand->u.pmcCmd.fReleaseWhenDone)
1930 {
1931 //This is a normal command, put it back to the free lsit
1932 pCommand->u.pmcCmd.size = 0;
1933 smeReleaseCommand( pMac, pCommand );
1934 }
1935 else
1936 {
1937 //this is a specially allocated comamnd due to out of command buffer. free it.
1938 palFreeMemory(pMac->hHdd, pCommand);
1939 }
1940}
1941
1942
1943//this function is used to abort a command where the normal processing of the command
1944//is terminated without going through the normal path. it is here to take care of callbacks for
1945//the command, if applicable.
1946void pmcAbortCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fStopping )
1947{
1948 if( eSmePmcCommandMask & pCommand->command )
1949 {
1950 if( !fStopping )
1951 {
1952 switch( pCommand->command )
1953 {
1954 case eSmeCommandEnterImps:
1955 smsLog(pMac, LOGE, FL("aborting request to enter IMPS\n"));
1956 pmcEnterFullPowerState(pMac);
1957 break;
1958
1959 case eSmeCommandExitImps:
1960 smsLog(pMac, LOGE, FL("aborting request to exit IMPS \n"));
1961 pmcEnterFullPowerState(pMac);
1962 break;
1963
1964 case eSmeCommandEnterBmps:
1965 smsLog(pMac, LOGE, FL("aborting request to enter BMPS \n"));
1966 pMac->pmc.bmpsRequestQueued = eANI_BOOLEAN_FALSE;
1967 pmcEnterFullPowerState(pMac);
1968 pmcDoBmpsCallbacks(pMac, eHAL_STATUS_FAILURE);
1969 break;
1970
1971 case eSmeCommandExitBmps:
1972 smsLog(pMac, LOGE, FL("aborting request to exit BMPS \n"));
1973 pmcEnterFullPowerState(pMac);
1974 break;
1975
1976 case eSmeCommandEnterUapsd:
1977 smsLog(pMac, LOGE, FL("aborting request to enter UAPSD \n"));
1978 //Since there is no retry for UAPSD, tell the requester here we are done with failure
1979 pMac->pmc.uapsdSessionRequired = FALSE;
1980 pmcDoStartUapsdCallbacks(pMac, eHAL_STATUS_FAILURE);
1981 break;
1982
1983 case eSmeCommandExitUapsd:
1984 smsLog(pMac, LOGE, FL("aborting request to exit UAPSD \n"));
1985 break;
1986
1987 case eSmeCommandEnterWowl:
1988 smsLog(pMac, LOGE, FL("aborting request to enter WOWL \n"));
1989 pmcDoEnterWowlCallbacks(pMac, eHAL_STATUS_FAILURE);
1990 break;
1991
1992 case eSmeCommandExitWowl:
1993 smsLog(pMac, LOGE, FL("aborting request to exit WOWL \n"));
1994 break;
1995
1996 case eSmeCommandEnterStandby:
1997 smsLog(pMac, LOGE, FL("aborting request to enter Standby \n"));
1998 pmcDoStandbyCallbacks(pMac, eHAL_STATUS_FAILURE);
1999 break;
2000
2001 default:
2002 smsLog(pMac, LOGE, FL("Request for PMC command (%d) is dropped\n"), pCommand->command);
2003 break;
2004 }
2005 }// !stopping
2006 pmcReleaseCommand( pMac, pCommand );
2007 }
2008}
2009
2010
2011
2012//These commands are not supposed to fail due to out of command buffer,
Jeff Johnsone7245742012-09-05 17:12:55 -07002013//otherwise other commands are not executed and no command is released. It will be deadlock.
Jeff Johnson295189b2012-06-20 16:38:30 -07002014#define PMC_IS_COMMAND_CANNOT_FAIL(cmdType)\
2015 ( (eSmeCommandEnterStandby == (cmdType )) ||\
2016 (eSmeCommandExitImps == (cmdType )) ||\
2017 (eSmeCommandExitBmps == (cmdType )) ||\
2018 (eSmeCommandExitUapsd == (cmdType )) ||\
2019 (eSmeCommandExitWowl == (cmdType )) )
2020
Jeff Johnsone7245742012-09-05 17:12:55 -07002021eHalStatus pmcPrepareCommand( tpAniSirGlobal pMac, eSmeCommandType cmdType, void *pvParam,
Jeff Johnson295189b2012-06-20 16:38:30 -07002022 tANI_U32 size, tSmeCmd **ppCmd )
2023{
2024 eHalStatus status = eHAL_STATUS_RESOURCES;
2025 tSmeCmd *pCommand = NULL;
2026
2027 VOS_ASSERT( ppCmd );
2028 do
2029 {
2030 pCommand = smeGetCommandBuffer( pMac );
2031 if ( pCommand )
2032 {
2033 //Make sure it will be put back to the list
2034 pCommand->u.pmcCmd.fReleaseWhenDone = FALSE;
2035 }
2036 else
2037 {
2038 smsLog( pMac, LOGE, FL(" fail to get command buffer for command 0x%X curState = %d"), cmdType, pMac->pmc.pmcState );
2039 //For certain PMC command, we cannot fail
2040 if( PMC_IS_COMMAND_CANNOT_FAIL(cmdType) )
2041 {
2042 smsLog( pMac, LOGE, FL(" command 0x%X cannot fail try allocating memory for it"), cmdType );
2043 status = palAllocateMemory(pMac->hHdd, (void **)&pCommand, sizeof(tSmeCmd));
2044 if(!HAL_STATUS_SUCCESS(status))
2045 {
Jeff Johnsone7245742012-09-05 17:12:55 -07002046 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 -07002047 __func__, cmdType);
Jeff Johnson295189b2012-06-20 16:38:30 -07002048 pCommand = NULL;
2049 break;
2050 }
2051 palZeroMemory(pMac->hHdd, pCommand, sizeof(tSmeCmd));
2052 //Make sure it will be free when it is done
2053 pCommand->u.pmcCmd.fReleaseWhenDone = TRUE;
2054 }
2055 else
2056 {
2057 break;
2058 }
2059 }
2060 pCommand->command = cmdType;
2061 pCommand->u.pmcCmd.size = size;
2062 //Initialize the reason code here. It may be overwritten later when
2063 //a particular reason is needed.
2064 pCommand->u.pmcCmd.fullPowerReason = eSME_REASON_OTHER;
2065 switch ( cmdType )
2066 {
2067 case eSmeCommandEnterImps:
2068 case eSmeCommandExitImps:
2069 case eSmeCommandEnterBmps:
2070 case eSmeCommandEnterUapsd:
2071 case eSmeCommandEnterStandby:
2072 status = eHAL_STATUS_SUCCESS;
2073 break;
2074
2075 case eSmeCommandExitUapsd:
2076 case eSmeCommandExitWowl:
2077 status = eHAL_STATUS_SUCCESS;
2078 if( pvParam )
2079 {
2080 pCommand->u.pmcCmd.fullPowerReason = *( (tRequestFullPowerReason *)pvParam );
2081 }
2082 break;
2083
2084 case eSmeCommandExitBmps:
2085 status = eHAL_STATUS_SUCCESS;
2086 if( pvParam )
2087 {
2088 pCommand->u.pmcCmd.u.exitBmpsInfo = *( (tExitBmpsInfo *)pvParam );
2089 pCommand->u.pmcCmd.fullPowerReason = pCommand->u.pmcCmd.u.exitBmpsInfo.exitBmpsReason;
2090 }
2091 else
2092 {
2093 smsLog( pMac, LOGE, (" exit BMPS must have a reason code\n") );
2094 }
2095 break;
2096
2097 case eSmeCommandEnterWowl:
2098 status = eHAL_STATUS_SUCCESS;
2099 if( pvParam )
2100 {
2101 pCommand->u.pmcCmd.u.enterWowlInfo = *( ( tSirSmeWowlEnterParams * )pvParam );
2102 }
2103 break;
2104
2105 default:
2106 smsLog( pMac, LOGE, FL(" invalid command type %d\n"), cmdType );
2107 status = eHAL_STATUS_INVALID_PARAMETER;
2108 break;
2109 }
2110
2111 } while( 0 );
2112
2113 if( HAL_STATUS_SUCCESS( status ) && pCommand )
2114 {
2115 *ppCmd = pCommand;
2116 }
2117 else if( pCommand )
2118 {
2119 pmcReleaseCommand( pMac, pCommand );
2120 }
2121
2122 return (status);
2123}
2124
2125
Jeff Johnsone7245742012-09-05 17:12:55 -07002126eHalStatus pmcIssueCommand( tpAniSirGlobal pMac, eSmeCommandType cmdType, void *pvParam,
Jeff Johnson295189b2012-06-20 16:38:30 -07002127 tANI_U32 size, tANI_BOOLEAN fPutToListHead )
2128{
2129 eHalStatus status = eHAL_STATUS_RESOURCES;
2130 tSmeCmd *pCommand = NULL;
2131
2132 status = pmcPrepareCommand( pMac, cmdType, pvParam, size, &pCommand );
2133 if( HAL_STATUS_SUCCESS( status ) && pCommand )
2134 {
2135 smePushCommand( pMac, pCommand, fPutToListHead );
2136 }
2137
2138 return( status );
2139}
2140
2141
2142
2143tANI_BOOLEAN pmcProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand )
2144{
2145 eHalStatus status = eHAL_STATUS_SUCCESS;
Jeff Johnson43971f52012-07-17 12:26:56 -07002146 VOS_STATUS vstatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07002147 tANI_BOOLEAN fRemoveCmd = eANI_BOOLEAN_TRUE;
2148
2149 do
2150 {
2151 switch ( pCommand->command )
2152 {
2153 case eSmeCommandEnterImps:
2154 if( FULL_POWER == pMac->pmc.pmcState )
2155 {
2156 status = pmcEnterImpsCheck( pMac );
2157 if( HAL_STATUS_SUCCESS( status ) )
2158 {
2159 /* Change state. */
2160 pMac->pmc.pmcState = REQUEST_IMPS;
2161 status = pmcSendMessage(pMac, eWNI_PMC_ENTER_IMPS_REQ, NULL, 0);
2162 if( HAL_STATUS_SUCCESS( status ) )
2163 {
2164 /* If we already went back Full Power State (meaning that request did not
2165 get as far as the device) then we are not successfull. */
2166 if ( FULL_POWER != pMac->pmc.pmcState )
2167 {
2168 fRemoveCmd = eANI_BOOLEAN_FALSE;
2169 }
2170 }
2171 }
2172 if( !HAL_STATUS_SUCCESS( status ) )
2173 {
2174 smsLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_IMPS_REQ or pmcEnterImpsCheck failed\n");
2175 pmcEnterFullPowerState( pMac );
2176 if(pmcShouldBmpsTimerRun(pMac))
2177 (void)pmcStartTrafficTimer(pMac, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
2178 }
2179 }//full_power
2180 break;
2181
2182 case eSmeCommandExitImps:
2183 pMac->pmc.requestFullPowerPending = FALSE;
2184 if( ( IMPS == pMac->pmc.pmcState ) || ( STANDBY == pMac->pmc.pmcState ) )
2185 {
2186 //Check state before sending message. The state may change after that
2187 if( STANDBY == pMac->pmc.pmcState )
2188 {
2189 //Enable Idle scan in CSR
2190 csrScanResumeIMPS(pMac);
2191 }
2192
2193 status = pmcSendMessage(pMac, eWNI_PMC_EXIT_IMPS_REQ, NULL, 0);
2194 if ( HAL_STATUS_SUCCESS( status ) )
2195 {
2196 pMac->pmc.pmcState = REQUEST_FULL_POWER;
Mohit Khanna23863762012-09-11 17:40:09 -07002197 smsLog(pMac, LOG2, FL("eWNI_PMC_EXIT_IMPS_REQ sent to PE\n"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002198 fRemoveCmd = eANI_BOOLEAN_FALSE;
2199 }
2200 else
2201 {
Jeff Johnsone7245742012-09-05 17:12:55 -07002202 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 -07002203 //Callbacks are called with success srarus, do we need to pass in real status??
2204 pmcEnterFullPowerState(pMac);
2205 }
2206 }
2207 break;
2208
2209 case eSmeCommandEnterBmps:
2210 if( FULL_POWER == pMac->pmc.pmcState )
2211 {
2212 //This function will not return success because the pmc state is not BMPS
2213 status = pmcEnterBmpsCheck( pMac );
2214 if( HAL_STATUS_SUCCESS( status ) )
2215 {
2216 /* Change PMC state */
2217 pMac->pmc.pmcState = REQUEST_BMPS;
Mohit Khanna23863762012-09-11 17:40:09 -07002218 smsLog(pMac, LOG2, "PMC: Enter BMPS req done: Force XO Core ON\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07002219 vstatus = vos_chipVoteXOCore(NULL, NULL, NULL, VOS_TRUE);
Jeff Johnson43971f52012-07-17 12:26:56 -07002220 if ( !VOS_IS_STATUS_SUCCESS(vstatus) )
Jeff Johnson295189b2012-06-20 16:38:30 -07002221 {
2222 smsLog(pMac, LOGE, "Could not turn XO Core ON. Can't go to BMPS\n");
2223 }
2224 else /* XO Core turn ON was successful */
2225 {
2226 /* Tell MAC to have device enter BMPS mode. */
2227 status = pmcSendMessage(pMac, eWNI_PMC_ENTER_BMPS_REQ, NULL, 0);
2228 if ( HAL_STATUS_SUCCESS( status ) )
2229 {
2230 fRemoveCmd = eANI_BOOLEAN_FALSE;
2231 }
2232 else
2233 {
2234 smsLog(pMac, LOGE, "Fail to send enter BMPS msg to PE\n");
2235 /* Cancel the vote for XO Core */
2236 smsLog(pMac, LOGW, "In module init: Cancel the vote for XO CORE ON "
2237 "since send enter bmps failed\n");
2238 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
2239 {
2240 smsLog(pMac, LOGE, "Could not cancel XO Core ON vote."
2241 "Not returning failure."
2242 "Power consumed will be high\n");
Jeff Johnsone7245742012-09-05 17:12:55 -07002243 }
2244
Jeff Johnson295189b2012-06-20 16:38:30 -07002245 }
2246 }
2247 }
2248 if( !HAL_STATUS_SUCCESS( status ) )
2249 {
2250 smsLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_BMPS_REQ status %d\n", status);
2251 pMac->pmc.bmpsRequestQueued = eANI_BOOLEAN_FALSE;
2252 pmcEnterFullPowerState(pMac);
2253 //Do not call UAPSD callback here since it may be retried
2254 pmcDoBmpsCallbacks(pMac, eHAL_STATUS_FAILURE);
2255 if(pmcShouldBmpsTimerRun(pMac))
2256 (void)pmcStartTrafficTimer(pMac, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
2257 }
2258 }
2259 break;
2260
2261 case eSmeCommandExitBmps:
2262 if( BMPS == pMac->pmc.pmcState )
2263 {
2264 pMac->pmc.requestFullPowerPending = FALSE;
2265
Jeff Johnsone7245742012-09-05 17:12:55 -07002266 status = pmcSendMessage( pMac, eWNI_PMC_EXIT_BMPS_REQ,
Jeff Johnson295189b2012-06-20 16:38:30 -07002267 &pCommand->u.pmcCmd.u.exitBmpsInfo, sizeof(tExitBmpsInfo) );
2268 if ( HAL_STATUS_SUCCESS( status ) )
2269 {
2270 pMac->pmc.pmcState = REQUEST_FULL_POWER;
2271 fRemoveCmd = eANI_BOOLEAN_FALSE;
Mohit Khanna23863762012-09-11 17:40:09 -07002272 smsLog(pMac, LOG2, FL("eWNI_PMC_EXIT_BMPS_REQ sent to PE\n"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002273
2274 }
2275 else
2276 {
2277 smsLog(pMac, LOGE, FL("eWNI_PMC_EXIT_BMPS_REQ fail to be sent to PE status %d\n"), status);
2278 pmcEnterFullPowerState(pMac);
2279 }
2280 }
2281 break;
2282
2283 case eSmeCommandEnterUapsd:
2284 if( BMPS == pMac->pmc.pmcState )
2285 {
2286 pMac->pmc.uapsdSessionRequired = TRUE;
2287 status = pmcSendMessage(pMac, eWNI_PMC_ENTER_UAPSD_REQ, NULL, 0);
2288 if ( HAL_STATUS_SUCCESS( status ) )
2289 {
2290 pMac->pmc.pmcState = REQUEST_START_UAPSD;
2291 fRemoveCmd = eANI_BOOLEAN_FALSE;
2292 }
2293 else
2294 {
2295 smsLog(pMac, LOGE, "PMC: failure to send message "
2296 "eWNI_PMC_ENTER_BMPS_REQ\n");
2297 //there is no retry for re-entering UAPSD so tell the requester we are done witgh failure.
2298 pMac->pmc.uapsdSessionRequired = FALSE;
2299 pmcDoStartUapsdCallbacks(pMac, eHAL_STATUS_FAILURE);
2300 }
2301 }
2302 break;
2303
2304 case eSmeCommandExitUapsd:
2305 if( UAPSD == pMac->pmc.pmcState )
2306 {
2307 pMac->pmc.requestFullPowerPending = FALSE;
2308 /* If already in REQUEST_STOP_UAPSD, simply return */
2309 if (pMac->pmc.pmcState == REQUEST_STOP_UAPSD)
2310 {
2311 break;
2312 }
2313
2314 /* Tell MAC to have device exit UAPSD mode. */
2315 status = pmcSendMessage(pMac, eWNI_PMC_EXIT_UAPSD_REQ, NULL, 0);
2316 if ( HAL_STATUS_SUCCESS( status ) )
2317 {
2318 /* Change state. Note that device will be put in BMPS state at the
2319 end of REQUEST_STOP_UAPSD state even if response is a failure*/
2320 pMac->pmc.pmcState = REQUEST_STOP_UAPSD;
2321 pMac->pmc.requestFullPowerPending = TRUE;
2322 pMac->pmc.requestFullPowerReason = pCommand->u.pmcCmd.fullPowerReason;
2323 fRemoveCmd = eANI_BOOLEAN_FALSE;
2324 }
2325 else
2326 {
2327 smsLog(pMac, LOGE, "PMC: failure to send message "
2328 "eWNI_PMC_EXIT_UAPSD_REQ\n");
2329 pmcEnterBmpsState(pMac);
2330 }
2331 }
2332
2333 break;
2334
2335 case eSmeCommandEnterWowl:
2336 if( ( BMPS == pMac->pmc.pmcState ) || ( WOWL == pMac->pmc.pmcState ) )
2337 {
Jeff Johnsone7245742012-09-05 17:12:55 -07002338 status = pmcSendMessage(pMac, eWNI_PMC_ENTER_WOWL_REQ,
Jeff Johnson295189b2012-06-20 16:38:30 -07002339 &pCommand->u.pmcCmd.u.enterWowlInfo, sizeof(tSirSmeWowlEnterParams));
2340 if ( HAL_STATUS_SUCCESS( status ) )
2341 {
2342 pMac->pmc.pmcState = REQUEST_ENTER_WOWL;
2343 fRemoveCmd = eANI_BOOLEAN_FALSE;
2344 }
2345 else
2346 {
2347 smsLog(pMac, LOGE, "PMC: failure to send message eWNI_PMC_ENTER_WOWL_REQ\n");
2348 pmcDoEnterWowlCallbacks(pMac, eHAL_STATUS_FAILURE);
2349 }
2350 }
2351 else
2352 {
2353 fRemoveCmd = eANI_BOOLEAN_TRUE;
2354 }
2355 break;
2356
2357 case eSmeCommandExitWowl:
2358 if( WOWL == pMac->pmc.pmcState )
2359 {
2360 pMac->pmc.requestFullPowerPending = FALSE;
2361 pMac->pmc.pmcState = REQUEST_EXIT_WOWL;
2362 status = pmcSendMessage(pMac, eWNI_PMC_EXIT_WOWL_REQ, NULL, 0);
2363 if ( HAL_STATUS_SUCCESS( status ) )
2364 {
2365 fRemoveCmd = eANI_BOOLEAN_FALSE;
2366 pMac->pmc.requestFullPowerPending = TRUE;
2367 pMac->pmc.requestFullPowerReason = pCommand->u.pmcCmd.fullPowerReason;
2368 }
2369 else
2370 {
2371 smsLog(pMac, LOGP, "PMC: failure to send message eWNI_PMC_EXIT_WOWL_REQ\n");
2372 pmcEnterBmpsState(pMac);
2373 }
2374 }
2375 break;
2376
2377 case eSmeCommandEnterStandby:
2378 if( FULL_POWER == pMac->pmc.pmcState )
2379 {
2380 //Disallow standby if concurrent sessions are present. Note that CSR would have
Jeff Johnsone7245742012-09-05 17:12:55 -07002381 //caused the STA to disconnect the Infra session (if not already disconnected) because of
Jeff Johnson295189b2012-06-20 16:38:30 -07002382 //standby request. But we are now failing the standby request because of concurrent session.
Jeff Johnsone7245742012-09-05 17:12:55 -07002383 //So was the tearing of infra session wasteful if we were going to fail the standby request ?
Jeff Johnson295189b2012-06-20 16:38:30 -07002384 //Not really. This is beacuse if and when BT-AMP etc sessions are torn down we will transition
2385 //to IMPS/standby and still save power.
2386 if (csrIsIBSSStarted(pMac) || csrIsBTAMPStarted(pMac))
2387 {
Jeff Johnsone7245742012-09-05 17:12:55 -07002388 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson295189b2012-06-20 16:38:30 -07002389 "WLAN: IBSS or BT-AMP session present. Cannot honor standby request");
2390
2391 pmcDoStandbyCallbacks(pMac, eHAL_STATUS_PMC_NOT_NOW);
2392 if(pmcShouldBmpsTimerRun(pMac))
2393 (void)pmcStartTrafficTimer(pMac, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
2394 break;
2395 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002396
Jeff Johnson295189b2012-06-20 16:38:30 -07002397 // Stop traffic timer. Just making sure timer is not running
2398 pmcStopTrafficTimer(pMac);
2399
2400 /* Change state. */
2401 pMac->pmc.pmcState = REQUEST_STANDBY;
2402
2403 /* Tell MAC to have device enter STANDBY mode. We are using the same message
2404 as IMPS mode to avoid code changes in layer below (PE/HAL)*/
2405 status = pmcSendMessage(pMac, eWNI_PMC_ENTER_IMPS_REQ, NULL, 0);
2406 if ( HAL_STATUS_SUCCESS( status ) )
2407 {
2408 //Disable Idle scan in CSR
2409 csrScanSuspendIMPS(pMac);
2410 fRemoveCmd = eANI_BOOLEAN_FALSE;
2411 }
2412 else
2413 {
2414 smsLog(pMac, LOGE, "PMC: failure to send message "
2415 "eWNI_PMC_ENTER_IMPS_REQ\n");
2416 pmcEnterFullPowerState(pMac);
2417 pmcDoStandbyCallbacks(pMac, eHAL_STATUS_FAILURE);
2418 /* Start the timer only if Auto BMPS feature is enabled or an UAPSD session is
2419 required */
2420 if(pmcShouldBmpsTimerRun(pMac))
2421 (void)pmcStartTrafficTimer(pMac, pMac->pmc.bmpsConfig.trafficMeasurePeriod);
2422 }
2423 }
2424 break;
2425
2426 default:
2427 smsLog( pMac, LOGE, FL(" invalid command type %d\n"), pCommand->command );
2428 break;
2429 }
2430
2431 } while( 0 );
2432
2433 return( fRemoveCmd );
2434}
2435
2436eHalStatus pmcEnterImpsCheck( tpAniSirGlobal pMac )
2437{
2438
2439 if( !PMC_IS_READY(pMac) )
2440 {
2441 smsLog(pMac, LOGE, FL("Requesting IMPS when PMC not ready\n"));
Jeff Johnsone7245742012-09-05 17:12:55 -07002442 smsLog(pMac, LOGE, FL("pmcReady = %d pmcState = %s\n"),
Jeff Johnson295189b2012-06-20 16:38:30 -07002443 pMac->pmc.pmcReady, pmcGetPmcStateStr(pMac->pmc.pmcState));
2444 return eHAL_STATUS_FAILURE;
2445 }
2446
2447 /* Check if IMPS is enabled. */
2448 if (!pMac->pmc.impsEnabled)
2449 {
2450 smsLog(pMac, LOG2, FL("IMPS is disabled\n"));
2451 return eHAL_STATUS_PMC_DISABLED;
2452 }
2453
2454 /* Check if IMPS enabled for current power source. */
2455 if ((pMac->pmc.powerSource == AC_POWER) && !pMac->pmc.impsConfig.enterOnAc)
2456 {
2457 smsLog(pMac, LOG2, FL("IMPS is disabled when operating on AC power\n"));
2458 return eHAL_STATUS_PMC_AC_POWER;
2459 }
2460
2461 /* Check that entry into a power save mode is allowed at this time. */
2462 if (!pmcPowerSaveCheck(pMac))
2463 {
2464 smsLog(pMac, LOG2, FL("IMPS cannot be entered now\n"));
2465 return eHAL_STATUS_PMC_NOT_NOW;
2466 }
2467
2468 /* Check that entry into a power save mode is allowed at this time if all
2469 running sessions agree. */
2470 if (!pmcAllowImps(pMac))
2471 {
2472 smsLog(pMac, LOG2, FL("IMPS cannot be entered now\n"));
2473 return eHAL_STATUS_PMC_NOT_NOW;
2474 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002475
Jeff Johnson295189b2012-06-20 16:38:30 -07002476 /* Check if already in IMPS. */
2477 if ((pMac->pmc.pmcState == REQUEST_IMPS) || (pMac->pmc.pmcState == IMPS) ||
2478 (pMac->pmc.pmcState == REQUEST_FULL_POWER))
2479 {
2480 smsLog(pMac, LOG2, FL("Already in IMPS\n"));
2481 return eHAL_STATUS_PMC_ALREADY_IN_IMPS;
2482 }
2483
2484 return ( eHAL_STATUS_SUCCESS );
2485}
2486
2487/* This API detrmines if it is ok to proceed with a Enter BMPS Request or not . Note when
2488 device is in BMPS/UAPSD states, this API returns failure because it is not ok to issue
2489 a BMPS request */
2490eHalStatus pmcEnterBmpsCheck( tpAniSirGlobal pMac )
2491{
2492
2493 /* Check if BMPS is enabled. */
2494 if (!pMac->pmc.bmpsEnabled)
2495 {
2496 smsLog(pMac, LOGE, "PMC: Cannot initiate BMPS. BMPS is disabled\n");
2497 return eHAL_STATUS_PMC_DISABLED;
2498 }
2499
2500 if( !PMC_IS_READY(pMac) )
2501 {
2502 smsLog(pMac, LOGE, FL("Requesting BMPS when PMC not ready\n"));
Jeff Johnsone7245742012-09-05 17:12:55 -07002503 smsLog(pMac, LOGE, FL("pmcReady = %d pmcState = %s\n"),
Jeff Johnson295189b2012-06-20 16:38:30 -07002504 pMac->pmc.pmcReady, pmcGetPmcStateStr(pMac->pmc.pmcState));
2505 return eHAL_STATUS_FAILURE;
2506 }
2507
2508 /* Check that we are associated with a single active session. */
2509 if (!pmcValidateConnectState( pMac ))
2510 {
2511 smsLog(pMac, LOGE, "PMC: STA not associated with an AP with single active session. BMPS cannot be entered\n");
2512 return eHAL_STATUS_FAILURE;
2513 }
2514
2515 /* BMPS can only be requested when device is in Full Power */
2516 if (pMac->pmc.pmcState != FULL_POWER)
2517 {
2518 smsLog(pMac, LOGE, "PMC: Device not in full power. Cannot request BMPS. pmcState %d\n", pMac->pmc.pmcState);
2519 return eHAL_STATUS_FAILURE;
2520 }
2521 /* Check that entry into a power save mode is allowed at this time. */
2522 if (!pmcPowerSaveCheck(pMac))
2523 {
2524 smsLog(pMac, LOGE, "PMC: Power save check failed. BMPS cannot be entered now\n");
2525 return eHAL_STATUS_PMC_NOT_NOW;
2526 }
2527
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07002528 //Remove this code once SLM_Sessionization is supported
2529 //BMPS_WORKAROUND_NOT_NEEDED
2530 if(!IS_FEATURE_SUPPORTED_BY_FW(SLM_SESSIONIZATION))
Mohit Khanna349bc392012-09-11 17:24:52 -07002531 {
2532 smsLog(pMac, LOG1, FL("doBMPSWorkaround %u\n"), pMac->roam.configParam.doBMPSWorkaround);
2533 if (pMac->roam.configParam.doBMPSWorkaround)
2534 {
2535 pMac->roam.configParam.doBMPSWorkaround = 0;
2536 smsLog(pMac, LOG1, FL("reset doBMPSWorkaround to disabled %u\n"), pMac->roam.configParam.doBMPSWorkaround);
2537 csrDisconnectAllActiveSessions(pMac);
2538 smsLog(pMac, LOGE, "PMC: doBMPSWorkaround was enabled. First Disconnect all sessions. pmcState %d\n", pMac->pmc.pmcState);
2539 return eHAL_STATUS_FAILURE;
2540 }
2541 }
2542
Jeff Johnson295189b2012-06-20 16:38:30 -07002543 return ( eHAL_STATUS_SUCCESS );
2544}
2545
2546tANI_BOOLEAN pmcShouldBmpsTimerRun( tpAniSirGlobal pMac )
2547{
Jeff Johnsone7245742012-09-05 17:12:55 -07002548 /* Check if BMPS is enabled and if Auto BMPS Feature is still enabled
Jeff Johnson295189b2012-06-20 16:38:30 -07002549 * or there is a pending Uapsd request or HDD requested BMPS or there
Jeff Johnsone7245742012-09-05 17:12:55 -07002550 * is a pending request for WoWL. In all these cases BMPS is required.
Jeff Johnson295189b2012-06-20 16:38:30 -07002551 * Otherwise just stop the timer and return.
2552 */
Jeff Johnsone7245742012-09-05 17:12:55 -07002553 if (!(pMac->pmc.bmpsEnabled && (pMac->pmc.autoBmpsEntryEnabled ||
Jeff Johnson295189b2012-06-20 16:38:30 -07002554 pMac->pmc.uapsdSessionRequired || pMac->pmc.bmpsRequestedByHdd ||
2555 pMac->pmc.wowlModeRequired )))
2556 {
2557 smsLog(pMac, LOG1, FL("BMPS is not enabled or not required"));
2558 return eANI_BOOLEAN_FALSE;
2559 }
2560
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05302561 if(pMac->pmc.isHostPsEn && pMac->pmc.remainInPowerActiveTillDHCP)
2562 {
2563 smsLog(pMac, LOG1, FL("Host controlled ps enabled and host wants active mode, so dont allow BMPS"));
2564 return eANI_BOOLEAN_FALSE;
2565 }
2566
Jeff Johnsone7245742012-09-05 17:12:55 -07002567 if ((vos_concurrent_sessions_running()) &&
2568 ((csrIsConcurrentInfraConnected( pMac ) ||
2569 (vos_get_concurrency_mode()& VOS_SAP) ||
2570 (vos_get_concurrency_mode()& VOS_P2P_GO))))
2571 {
2572 smsLog(pMac, LOG1, FL("Multiple Sessions/GO/SAP sessions . BMPS should not be started"));
2573 return eANI_BOOLEAN_FALSE;
2574 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002575 /* Check if there is an Infra session. BMPS is possible only if there is
Jeff Johnson295189b2012-06-20 16:38:30 -07002576 * an Infra session */
2577 if (!csrIsInfraConnected(pMac))
2578 {
2579 smsLog(pMac, LOG1, FL("No Infra Session or multiple sessions. BMPS should not be started"));
2580 return eANI_BOOLEAN_FALSE;
2581 }
2582 return eANI_BOOLEAN_TRUE;
2583}
2584
2585
Jeff Johnsone7245742012-09-05 17:12:55 -07002586#ifdef FEATURE_WLAN_DIAG_SUPPORT
Jeff Johnson295189b2012-06-20 16:38:30 -07002587
2588#define PMC_DIAG_EVT_TIMER_INTERVAL ( 5000 )
2589
2590void pmcDiagEvtTimerExpired (tHalHandle hHal)
2591{
2592 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
2593 WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
2594
2595 vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
2596 psRequest.event_subtype = WLAN_PMC_CURRENT_STATE;
2597 psRequest.pmc_current_state = pMac->pmc.pmcState;
2598
2599 WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
2600
2601 smsLog(pMac, LOGW, FL("DIAG event timer expired\n"));
2602
2603 /* re-arm timer */
2604 if (pmcStartDiagEvtTimer(hHal) != eHAL_STATUS_SUCCESS)
2605 {
2606 smsLog(pMac, LOGP, FL("Cannot re-arm DIAG evt timer\n"));
2607 }
2608}
2609
2610eHalStatus pmcStartDiagEvtTimer (tHalHandle hHal)
2611{
2612 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
2613
2614 smsLog(pMac, LOG2, FL("Entering pmcStartDiagEvtTimer\n"));
2615
2616 if (palTimerStart(pMac->hHdd, pMac->pmc.hDiagEvtTimer, PMC_DIAG_EVT_TIMER_INTERVAL *
2617 1000, TRUE) != eHAL_STATUS_SUCCESS)
2618 {
2619 smsLog(pMac, LOGP, FL("Cannot start DIAG evt timer\n"));
2620 return eHAL_STATUS_FAILURE;
2621 }
2622
2623 return eHAL_STATUS_SUCCESS;
2624}
2625
2626void pmcStopDiagEvtTimer (tHalHandle hHal)
2627{
2628 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
2629 smsLog(pMac, LOG2, FL("Entering pmcStopDiagEvtTimer\n"));
2630 (void)palTimerStop(pMac->hHdd, pMac->pmc.hDiagEvtTimer);
2631}
2632#endif