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