blob: a8fe6f6f3b7a89b24958daa90898fe135040942b [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
2 * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/******************************************************************************
23*
24* Name: pmcApi.c
25*
26* Description: Routines that make up the Power Management Control (PMC) API.
27*
28* Copyright 2008 (c) Qualcomm, Incorporated.
29* All Rights Reserved.
30* Qualcomm Confidential and Proprietary.
31*
32******************************************************************************/
33
34#include "palTypes.h"
35#include "aniGlobal.h"
36#include "palTimer.h"
37#include "csrLinkList.h"
38#include "smsDebug.h"
39#include "pmcApi.h"
40#include "pmc.h"
41#include "cfgApi.h"
42#include "smeInside.h"
43#include "csrInsideApi.h"
44#include "wlan_ps_wow_diag.h"
45#include "wlan_qct_wda.h"
46#include "limSessionUtils.h"
47#include "csrInsideApi.h"
48
49extern void pmcReleaseCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand );
50
51void pmcCloseDeferredMsgList(tpAniSirGlobal pMac);
52void pmcCloseDeviceStateUpdateList(tpAniSirGlobal pMac);
53void pmcCloseRequestStartUapsdList(tpAniSirGlobal pMac);
54void pmcCloseRequestBmpsList(tpAniSirGlobal pMac);
55void pmcCloseRequestFullPowerList(tpAniSirGlobal pMac);
56void pmcClosePowerSaveCheckList(tpAniSirGlobal pMac);
57
58/******************************************************************************
59*
60* Name: pmcOpen
61*
62* Description:
63* Does a PMC open operation on the device.
64*
65* Parameters:
66* hHal - HAL handle for device
67*
68* Returns:
69* eHAL_STATUS_SUCCESS - open successful
70* eHAL_STATUS_FAILURE - open not successful
71*
72******************************************************************************/
73eHalStatus pmcOpen (tHalHandle hHal)
74{
75 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
76
77 smsLog(pMac, LOG2, FL("Entering pmcOpen\n"));
78
79 /* Initialize basic PMC information about device. */
80 pMac->pmc.powerSource = BATTERY_POWER;
81 pMac->pmc.pmcState = STOPPED;
82 pMac->pmc.pmcReady = FALSE;
83
84 /* Initialize Power Save Modes */
85 pMac->pmc.impsEnabled = FALSE;
86 pMac->pmc.autoBmpsEntryEnabled = FALSE;
87 pMac->pmc.smpsEnabled = FALSE;
88 pMac->pmc.uapsdEnabled = TRUE;
89 pMac->pmc.bmpsEnabled = TRUE;
90 pMac->pmc.standbyEnabled = TRUE;
91 pMac->pmc.wowlEnabled = TRUE;
92 pMac->pmc.rfSuppliesVotedOff= FALSE;
93
94 palZeroMemory(pMac->hHdd, &(pMac->pmc.bmpsConfig), sizeof(tPmcBmpsConfigParams));
95 palZeroMemory(pMac->hHdd, &(pMac->pmc.impsConfig), sizeof(tPmcImpsConfigParams));
96 palZeroMemory(pMac->hHdd, &(pMac->pmc.smpsConfig), sizeof(tPmcSmpsConfigParams));
97
98 /* Allocate a timer to use with IMPS. */
99 if (palTimerAlloc(pMac->hHdd, &pMac->pmc.hImpsTimer, pmcImpsTimerExpired, hHal) != eHAL_STATUS_SUCCESS)
100 {
101 smsLog(pMac, LOGE, FL("Cannot allocate timer for IMPS\n"));
102 return eHAL_STATUS_FAILURE;
103 }
104
105 /* Allocate a timer used in Full Power State to measure traffic
106 levels and determine when to enter BMPS. */
107 if (!VOS_IS_STATUS_SUCCESS(vos_timer_init(&pMac->pmc.hTrafficTimer,
108 VOS_TIMER_TYPE_SW, pmcTrafficTimerExpired, hHal)))
109 {
110 smsLog(pMac, LOGE, FL("Cannot allocate timer for traffic measurement\n"));
111 return eHAL_STATUS_FAILURE;
112 }
113
114#ifdef FEATURE_WLAN_DIAG_SUPPORT
115 /* Allocate a timer used to report current PMC state through periodic DIAG event */
116 if (palTimerAlloc(pMac->hHdd, &pMac->pmc.hDiagEvtTimer, pmcDiagEvtTimerExpired, hHal) != eHAL_STATUS_SUCCESS)
117 {
118 smsLog(pMac, LOGE, FL("Cannot allocate timer for diag event reporting\n"));
119 return eHAL_STATUS_FAILURE;
120 }
121#endif
122
123 //Initialize the default value for Bmps related config.
124 pMac->pmc.bmpsConfig.trafficMeasurePeriod = BMPS_TRAFFIC_TIMER_DEFAULT;
125 pMac->pmc.bmpsConfig.bmpsPeriod = WNI_CFG_LISTEN_INTERVAL_STADEF;
126
127 /* Allocate a timer used to schedule a deferred power save mode exit. */
128 if (palTimerAlloc(pMac->hHdd, &pMac->pmc.hExitPowerSaveTimer,
129 pmcExitPowerSaveTimerExpired, hHal) != eHAL_STATUS_SUCCESS)
130 {
131 smsLog(pMac, LOGE, FL("Cannot allocate exit power save mode timer\n"));
132 PMC_ABORT;
133 return eHAL_STATUS_FAILURE;
134 }
135
136 /* Initialize lists for power save check routines and request full power callback routines. */
137 if (csrLLOpen(pMac->hHdd, &pMac->pmc.powerSaveCheckList) != eHAL_STATUS_SUCCESS)
138 {
139 smsLog(pMac, LOGE, FL("Cannot initialize power save check routine list\n"));
140 PMC_ABORT;
141 return eHAL_STATUS_FAILURE;
142 }
143 if (csrLLOpen(pMac->hHdd, &pMac->pmc.requestFullPowerList) != eHAL_STATUS_SUCCESS)
144 {
145 smsLog(pMac, LOGE, FL("Cannot initialize request full power callback routine list\n"));
146 PMC_ABORT;
147 return eHAL_STATUS_FAILURE;
148 }
149
150 /* Initialize lists for request BMPS callback routines. */
151 if (csrLLOpen(pMac->hHdd, &pMac->pmc.requestBmpsList) !=
152 eHAL_STATUS_SUCCESS)
153 {
154 smsLog(pMac, LOGE, "PMC: cannot initialize request BMPS callback routine list\n");
155 return eHAL_STATUS_FAILURE;
156 }
157
158 /* Initialize lists for request start UAPSD callback routines. */
159 if (csrLLOpen(pMac->hHdd, &pMac->pmc.requestStartUapsdList) != eHAL_STATUS_SUCCESS)
160 {
161 smsLog(pMac, LOGE, "PMC: cannot initialize request start UAPSD callback routine list\n");
162 return eHAL_STATUS_FAILURE;
163 }
164
165 /* Initialize lists for device state update indication callback routines. */
166 if (csrLLOpen(pMac->hHdd, &pMac->pmc.deviceStateUpdateIndList) != eHAL_STATUS_SUCCESS)
167 {
168 smsLog(pMac, LOGE, "PMC: cannot initialize device state update indication callback list\n");
169 return eHAL_STATUS_FAILURE;
170 }
171
172 if (csrLLOpen(pMac->hHdd, &pMac->pmc.deferredMsgList) != eHAL_STATUS_SUCCESS)
173 {
174 smsLog(pMac, LOGE, FL("Cannot initialize deferred msg list\n"));
175 PMC_ABORT;
176 return eHAL_STATUS_FAILURE;
177 }
178
179 return eHAL_STATUS_SUCCESS;
180}
181
182
183/******************************************************************************
184*
185* Name: pmcStart
186*
187* Description:
188* Does a PMC start operation on the device.
189*
190* Parameters:
191* hHal - HAL handle for device
192*
193* Returns:
194* eHAL_STATUS_SUCCESS - start successful
195* eHAL_STATUS_FAILURE - start not successful
196*
197******************************************************************************/
198eHalStatus pmcStart (tHalHandle hHal)
199{
200 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
201 tSirMacHTMIMOPowerSaveState htMimoPowerSaveState;
202
203 smsLog(pMac, LOG2, FL("Entering pmcStart\n"));
204
205 /* Initialize basic PMC information about device. */
206 pMac->pmc.pmcState = FULL_POWER;
207 pMac->pmc.requestFullPowerPending = FALSE;
208 pMac->pmc.uapsdSessionRequired = FALSE;
209 pMac->pmc.wowlModeRequired = FALSE;
210 pMac->pmc.bmpsRequestedByHdd = FALSE;
211 pMac->pmc.remainInPowerActiveTillDHCP = FALSE;
212 pMac->pmc.remainInPowerActiveThreshold = 0;
213
214 /* WLAN Switch initial states. */
215 pMac->pmc.hwWlanSwitchState = ePMC_SWITCH_ON;
216 pMac->pmc.swWlanSwitchState = ePMC_SWITCH_ON;
217
218 /* No IMPS callback routine yet. */
219 pMac->pmc.impsCallbackRoutine = NULL;
220
221 /* No STANDBY callback routine yet. */
222 pMac->pmc.standbyCallbackRoutine = NULL;
223
224 /* No WOWL callback routine yet. */
225 pMac->pmc.enterWowlCallbackRoutine = NULL;
226
227 /* Initialize BMPS traffic counts. */
228 pMac->pmc.cLastTxUnicastFrames = 0;
229 pMac->pmc.cLastRxUnicastFrames = 0;
230
231 /* Configure SMPS. */
232 if (pMac->pmc.smpsEnabled && (pMac->pmc.powerSource != AC_POWER || pMac->pmc.smpsConfig.enterOnAc))
233 {
234 if (pMac->pmc.smpsConfig.mode == ePMC_DYNAMIC_SMPS)
235 htMimoPowerSaveState = eSIR_HT_MIMO_PS_DYNAMIC;
236 if (pMac->pmc.smpsConfig.mode == ePMC_STATIC_SMPS)
237 htMimoPowerSaveState = eSIR_HT_MIMO_PS_STATIC;
238 }
239 else
240 htMimoPowerSaveState = eSIR_HT_MIMO_PS_NO_LIMIT;
241
242 if (pmcSendMessage(hHal, eWNI_PMC_SMPS_STATE_IND, &htMimoPowerSaveState,
243 sizeof(tSirMacHTMIMOPowerSaveState)) != eHAL_STATUS_SUCCESS)
244 return eHAL_STATUS_FAILURE;
245
246#ifdef FEATURE_WLAN_DIAG_SUPPORT
247 if (pmcStartDiagEvtTimer(hHal) != eHAL_STATUS_SUCCESS)
248 {
249 return eHAL_STATUS_FAILURE;
250 }
251#endif
252
253#if defined(ANI_LOGDUMP)
254 pmcDumpInit(hHal);
255#endif
256
257 return eHAL_STATUS_SUCCESS;
258}
259
260
261/******************************************************************************
262*
263* Name: pmcStop
264*
265* Description:
266* Does a PMC stop operation on the device.
267*
268* Parameters:
269* hHal - HAL handle for device
270*
271* Returns:
272* eHAL_STATUS_SUCCESS - stop successful
273* eHAL_STATUS_FAILURE - stop not successful
274*
275******************************************************************************/
276eHalStatus pmcStop (tHalHandle hHal)
277{
278 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
279 tListElem *pEntry;
280 tPmcDeferredMsg *pDeferredMsg;
281
282 smsLog(pMac, LOG2, FL("Entering pmcStop\n"));
283
284 /* Cancel any running timers. */
285 if (palTimerStop(pMac->hHdd, pMac->pmc.hImpsTimer) != eHAL_STATUS_SUCCESS)
286 {
287 smsLog(pMac, LOGE, FL("Cannot cancel IMPS timer\n"));
288 }
289
290 pmcStopTrafficTimer(hHal);
291
292#ifdef FEATURE_WLAN_DIAG_SUPPORT
293 pmcStopDiagEvtTimer(hHal);
294#endif
295
296 if (palTimerStop(pMac->hHdd, pMac->pmc.hExitPowerSaveTimer) != eHAL_STATUS_SUCCESS)
297 {
298 smsLog(pMac, LOGE, FL("Cannot cancel exit power save mode timer\n"));
299 }
300
301 /* Do all the callbacks. */
302 pmcDoCallbacks(hHal, eHAL_STATUS_FAILURE);
303 pmcDoBmpsCallbacks(hHal, eHAL_STATUS_FAILURE);
304 pMac->pmc.uapsdSessionRequired = FALSE;
305 pmcDoStartUapsdCallbacks(hHal, eHAL_STATUS_FAILURE);
306 pmcDoStandbyCallbacks(hHal, eHAL_STATUS_FAILURE);
307
308 //purge the deferred msg list
309 csrLLLock( &pMac->pmc.deferredMsgList );
310 while( NULL != ( pEntry = csrLLRemoveHead( &pMac->pmc.deferredMsgList, eANI_BOOLEAN_FALSE ) ) )
311 {
312 pDeferredMsg = GET_BASE_ADDR( pEntry, tPmcDeferredMsg, link );
313 palFreeMemory( pMac->hHdd, pDeferredMsg );
314 }
315 csrLLUnlock( &pMac->pmc.deferredMsgList );
316
317 /* PMC is stopped. */
318 pMac->pmc.pmcState = STOPPED;
319 pMac->pmc.pmcReady = FALSE;
320
321 return eHAL_STATUS_SUCCESS;
322}
323
324
325/******************************************************************************
326*
327* Name: pmcClose
328*
329* Description:
330* Does a PMC close operation on the device.
331*
332* Parameters:
333* hHal - HAL handle for device
334*
335* Returns:
336* eHAL_STATUS_SUCCESS - close successful
337* eHAL_STATUS_FAILURE - close not successful
338*
339******************************************************************************/
340eHalStatus pmcClose (tHalHandle hHal)
341{
342 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
343
344 smsLog(pMac, LOG2, FL("Entering pmcClose\n"));
345
346 /* Free up allocated resources. */
347 if (palTimerFree(pMac->hHdd, pMac->pmc.hImpsTimer) != eHAL_STATUS_SUCCESS)
348 {
349 smsLog(pMac, LOGE, FL("Cannot deallocate IMPS timer\n"));
350 }
351 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(&pMac->pmc.hTrafficTimer)))
352 {
353 smsLog(pMac, LOGE, FL("Cannot deallocate traffic timer\n"));
354 }
355#ifdef FEATURE_WLAN_DIAG_SUPPORT
356 if (palTimerFree(pMac->hHdd, pMac->pmc.hDiagEvtTimer) != eHAL_STATUS_SUCCESS)
357 {
358 smsLog(pMac, LOGE, FL("Cannot deallocate timer for diag event reporting\n"));
359 }
360#endif
361 if (palTimerFree(pMac->hHdd, pMac->pmc.hExitPowerSaveTimer) != eHAL_STATUS_SUCCESS)
362 {
363 smsLog(pMac, LOGE, FL("Cannot deallocate exit power save mode timer\n"));
364 }
365
366 /*
367 The following list's entries are dynamically allocated so they need their own
368 cleanup function
369 */
370 pmcClosePowerSaveCheckList(pMac);
371 pmcCloseRequestFullPowerList(pMac);
372 pmcCloseRequestBmpsList(pMac);
373 pmcCloseRequestStartUapsdList(pMac);
374 pmcCloseDeviceStateUpdateList(pMac);
375 pmcCloseDeferredMsgList(pMac);
376
377 return eHAL_STATUS_SUCCESS;
378}
379
380
381/******************************************************************************
382*
383* Name: pmcSignalPowerEvent
384*
385* Description:
386* Signals to PMC that a power event has occurred.
387*
388* Parameters:
389* hHal - HAL handle for device
390* event - the event that has occurred
391*
392* Returns:
393* eHAL_STATUS_SUCCESS - signaling successful
394* eHAL_STATUS_FAILURE - signaling not successful
395*
396******************************************************************************/
397eHalStatus pmcSignalPowerEvent (tHalHandle hHal, tPmcPowerEvent event)
398{
399 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
400#ifndef GEN6_ONWARDS
401 tSirMacHTMIMOPowerSaveState htMimoPowerSaveState;
402#endif
403
404 smsLog(pMac, LOG2, FL("Entering pmcSignalPowerEvent, event %d\n"), event);
405
406 /* Take action based on the event being signaled. */
407 switch (event)
408 {
409#ifndef GEN6_ONWARDS
410 case ePMC_SYSTEM_HIBERNATE:
411 return pmcEnterLowPowerState(hHal);
412
413 case ePMC_SYSTEM_RESUME:
414 return pmcExitLowPowerState(hHal);
415
416 case ePMC_HW_WLAN_SWITCH_OFF:
417 pMac->pmc.hwWlanSwitchState = ePMC_SWITCH_OFF;
418 return pmcEnterLowPowerState(hHal);
419
420 case ePMC_HW_WLAN_SWITCH_ON:
421 pMac->pmc.hwWlanSwitchState = ePMC_SWITCH_ON;
422 return pmcExitLowPowerState(hHal);
423
424 case ePMC_SW_WLAN_SWITCH_OFF:
425 pMac->pmc.swWlanSwitchState = ePMC_SWITCH_OFF;
426 return pmcEnterLowPowerState(hHal);
427
428 case ePMC_SW_WLAN_SWITCH_ON:
429 pMac->pmc.swWlanSwitchState = ePMC_SWITCH_ON;
430 return pmcExitLowPowerState(hHal);
431
432 case ePMC_BATTERY_OPERATION:
433 pMac->pmc.powerSource = BATTERY_POWER;
434
435 /* Turn on SMPS. */
436 if (pMac->pmc.smpsEnabled)
437 {
438 if (pMac->pmc.smpsConfig.mode == ePMC_DYNAMIC_SMPS)
439 htMimoPowerSaveState = eSIR_HT_MIMO_PS_DYNAMIC;
440 if (pMac->pmc.smpsConfig.mode == ePMC_STATIC_SMPS)
441 htMimoPowerSaveState = eSIR_HT_MIMO_PS_STATIC;
442 if (pmcSendMessage(hHal, eWNI_PMC_SMPS_STATE_IND, &htMimoPowerSaveState,
443 sizeof(tSirMacHTMIMOPowerSaveState)) != eHAL_STATUS_SUCCESS)
444 return eHAL_STATUS_FAILURE;
445 }
446 return eHAL_STATUS_SUCCESS;
447
448 case ePMC_AC_OPERATION:
449 pMac->pmc.powerSource = AC_POWER;
450
451 /* Turn off SMPS. */
452 if (!pMac->pmc.smpsConfig.enterOnAc)
453 {
454 htMimoPowerSaveState = eSIR_HT_MIMO_PS_NO_LIMIT;
455 if (pmcSendMessage(hHal, eWNI_PMC_SMPS_STATE_IND, &htMimoPowerSaveState,
456 sizeof(tSirMacHTMIMOPowerSaveState)) != eHAL_STATUS_SUCCESS)
457 return eHAL_STATUS_FAILURE;
458 }
459 return eHAL_STATUS_SUCCESS;
460#endif //GEN6_ONWARDS
461 default:
462 smsLog(pMac, LOGE, FL("Invalid event %d\n"), event);
463 PMC_ABORT;
464 return eHAL_STATUS_FAILURE;
465 }
466}
467
468
469/******************************************************************************
470*
471* Name: pmcSetConfigPowerSave
472*
473* Description:
474* Configures one of the power saving modes.
475*
476* Parameters:
477* hHal - HAL handle for device
478* psMode - the power saving mode to configure
479* pConfigParams - pointer to configuration parameters specific to the
480* power saving mode
481*
482* Returns:
483* eHAL_STATUS_SUCCESS - configuration successful
484* eHAL_STATUS_FAILURE - configuration not successful
485*
486******************************************************************************/
487eHalStatus pmcSetConfigPowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode, void *pConfigParams)
488{
489 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
490
491#ifdef FEATURE_WLAN_DIAG_SUPPORT
492 WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
493#endif
494
495 smsLog(pMac, LOG2, FL("Entering pmcSetConfigPowerSave, power save mode %d\n"), psMode);
496
497 /* Configure the specified power saving mode. */
498 switch (psMode)
499 {
500
501 case ePMC_IDLE_MODE_POWER_SAVE:
502 pMac->pmc.impsConfig = *(tpPmcImpsConfigParams)pConfigParams;
503 smsLog(pMac, LOG3, FL("IMPS configuration"));
504 smsLog(pMac, LOG3, " enter on AC: %d\n",
505 pMac->pmc.impsConfig.enterOnAc);
506 break;
507
508 case ePMC_BEACON_MODE_POWER_SAVE:
509 pMac->pmc.bmpsConfig = *(tpPmcBmpsConfigParams)pConfigParams;
510 smsLog(pMac, LOG3, FL("BMPS configuration"));
511 smsLog(pMac, LOG3, " enter on AC: %d\n",
512 pMac->pmc.bmpsConfig.enterOnAc);
513 smsLog(pMac, LOG3, " TX threshold: %d\n",
514 pMac->pmc.bmpsConfig.txThreshold);
515 smsLog(pMac, LOG3, " RX threshold: %d\n",
516 pMac->pmc.bmpsConfig.rxThreshold);
517 smsLog(pMac, LOG3, " traffic measurement period (ms): %d\n",
518 pMac->pmc.bmpsConfig.trafficMeasurePeriod);
519 smsLog(pMac, LOG3, " BMPS period: %d\n",
520 pMac->pmc.bmpsConfig.bmpsPeriod);
521 smsLog(pMac, LOG3, " beacons to forward code: %d\n",
522 pMac->pmc.bmpsConfig.forwardBeacons);
523 smsLog(pMac, LOG3, " value of N: %d\n",
524 pMac->pmc.bmpsConfig.valueOfN);
525 smsLog(pMac, LOG3, " use PS poll: %d\n",
526 pMac->pmc.bmpsConfig.usePsPoll);
527 smsLog(pMac, LOG3, " set PM on last frame: %d\n",
528 pMac->pmc.bmpsConfig.setPmOnLastFrame);
529 smsLog(pMac, LOG3, " value of enableBeaconEarlyTermination: %d\n",
530 pMac->pmc.bmpsConfig.enableBeaconEarlyTermination);
531 smsLog(pMac, LOG3, " value of bcnEarlyTermWakeInterval: %d\n",
532 pMac->pmc.bmpsConfig.bcnEarlyTermWakeInterval);
533
534#ifdef FEATURE_WLAN_DIAG_SUPPORT
535 vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
536 psRequest.event_subtype = WLAN_BMPS_SET_CONFIG;
537 /* possible loss of data due to mismatch but expectation is that
538 values can reasonably be expected to fit in target widths */
539 psRequest.bmps_auto_timer_duration = (v_U16_t)pMac->pmc.bmpsConfig.trafficMeasurePeriod;
540 psRequest.bmps_period = (v_U16_t)pMac->pmc.bmpsConfig.bmpsPeriod;
541
542 WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
543#endif
544
545
546 break;
547
548 case ePMC_SPATIAL_MULTIPLEX_POWER_SAVE:
549 pMac->pmc.smpsConfig = *(tpPmcSmpsConfigParams)pConfigParams;
550 smsLog(pMac, LOG3, FL("SMPS configuration"));
551 smsLog(pMac, LOG3, " mode: %d\n", pMac->pmc.smpsConfig.mode);
552 smsLog(pMac, LOG3, " enter on AC: %d\n",
553 pMac->pmc.smpsConfig.enterOnAc);
554 break;
555
556 default:
557 smsLog(pMac, LOGE, FL("Invalid power save mode %d\n"), psMode);
558 PMC_ABORT;
559 return eHAL_STATUS_FAILURE;
560 }
561
562 //Send the power save config down to PE/HAL/FW if BMPS mode is being configured
563 //and pmcReady has been invoked
564 if(PMC_IS_READY(pMac) && psMode == ePMC_BEACON_MODE_POWER_SAVE)
565 {
566 if (pmcSendPowerSaveConfigMessage(hHal) != eHAL_STATUS_SUCCESS)
567 return eHAL_STATUS_FAILURE;
568 }
569
570 return eHAL_STATUS_SUCCESS;
571}
572
573/******************************************************************************
574*
575* Name: pmcGetConfigPowerSave
576*
577* Description:
578* Get the config for the specified power save mode
579*
580* Parameters:
581* hHal - HAL handle for device
582* psMode - the power saving mode to configure
583* pConfigParams - pointer to configuration parameters specific to the
584* power saving mode
585*
586* Returns:
587* eHAL_STATUS_SUCCESS - configuration successful
588* eHAL_STATUS_FAILURE - configuration not successful
589*
590******************************************************************************/
591eHalStatus pmcGetConfigPowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode, void *pConfigParams)
592{
593 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
594
595 smsLog(pMac, LOG2, FL("Entering pmcGetConfigPowerSave, power save mode %d\n"), psMode);
596
597 /* Configure the specified power saving mode. */
598 switch (psMode)
599 {
600
601 case ePMC_IDLE_MODE_POWER_SAVE:
602 *(tpPmcImpsConfigParams)pConfigParams = pMac->pmc.impsConfig;
603 break;
604
605 case ePMC_BEACON_MODE_POWER_SAVE:
606 *(tpPmcBmpsConfigParams)pConfigParams = pMac->pmc.bmpsConfig;
607 break;
608
609 case ePMC_SPATIAL_MULTIPLEX_POWER_SAVE:
610 *(tpPmcSmpsConfigParams)pConfigParams = pMac->pmc.smpsConfig;
611 break;
612
613 default:
614 smsLog(pMac, LOGE, FL("Invalid power save mode %d\n"), psMode);
615 return eHAL_STATUS_FAILURE;
616 }
617
618 return eHAL_STATUS_SUCCESS;
619}
620/******************************************************************************
621*
622* Name: pmcEnablePowerSave
623*
624* Description:
625* Enables one of the power saving modes.
626*
627* Parameters:
628* hHal - HAL handle for device
629* psMode - the power saving mode to enable
630*
631* Returns:
632* eHAL_STATUS_SUCCESS - successfully enabled
633* eHAL_STATUS_FAILURE - not successfully enabled
634*
635******************************************************************************/
636eHalStatus pmcEnablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode)
637{
638 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
639 tSirMacHTMIMOPowerSaveState htMimoPowerSaveState;
640
641#ifdef FEATURE_WLAN_DIAG_SUPPORT
642 WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
643
644 vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
645 psRequest.event_subtype = WLAN_PS_MODE_ENABLE_REQ;
646 psRequest.enable_disable_powersave_mode = psMode;
647
648 WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
649#endif
650
651 smsLog(pMac, LOG2, FL("Entering pmcEnablePowerSave, power save mode %d\n"), psMode);
652
653 /* Enable the specified power saving mode. */
654 switch (psMode)
655 {
656
657 case ePMC_IDLE_MODE_POWER_SAVE:
658 pMac->pmc.impsEnabled = TRUE;
659 break;
660
661 case ePMC_BEACON_MODE_POWER_SAVE:
662 pMac->pmc.bmpsEnabled = TRUE;
663 break;
664
665 case ePMC_SPATIAL_MULTIPLEX_POWER_SAVE:
666 pMac->pmc.smpsEnabled = TRUE;
667
668 /* If PMC already started, then turn on SMPS. */
669 if (pMac->pmc.pmcState != STOPPED)
670 if (pMac->pmc.powerSource != AC_POWER ||
671 pMac->pmc.smpsConfig.enterOnAc)
672 {
673 if (pMac->pmc.smpsConfig.mode == ePMC_DYNAMIC_SMPS)
674 htMimoPowerSaveState = eSIR_HT_MIMO_PS_DYNAMIC;
675 if (pMac->pmc.smpsConfig.mode == ePMC_STATIC_SMPS)
676 htMimoPowerSaveState = eSIR_HT_MIMO_PS_STATIC;
677 if (pmcSendMessage(hHal, eWNI_PMC_SMPS_STATE_IND, &htMimoPowerSaveState,
678 sizeof(tSirMacHTMIMOPowerSaveState)) != eHAL_STATUS_SUCCESS)
679 return eHAL_STATUS_FAILURE;
680 }
681 break;
682
683 case ePMC_UAPSD_MODE_POWER_SAVE:
684 pMac->pmc.uapsdEnabled = TRUE;
685 break;
686
687 case ePMC_STANDBY_MODE_POWER_SAVE:
688 pMac->pmc.standbyEnabled = TRUE;
689 break;
690
691 case ePMC_WOWL_MODE_POWER_SAVE:
692 pMac->pmc.wowlEnabled = TRUE;
693 break;
694
695 default:
696 smsLog(pMac, LOGE, FL("Invalid power save mode %d\n"), psMode);
697 PMC_ABORT;
698 return eHAL_STATUS_FAILURE;
699 }
700
701 return eHAL_STATUS_SUCCESS;
702}
703/* ---------------------------------------------------------------------------
704 \fn pmcStartAutoBmpsTimer
705 \brief Starts a timer that periodically polls all the registered
706 module for entry into Bmps mode. This timer is started only if BMPS is
707 enabled and whenever the device is in full power.
708 \param hHal - The handle returned by macOpen.
709 \return eHalStatus
710 ---------------------------------------------------------------------------*/
711eHalStatus pmcStartAutoBmpsTimer (tHalHandle hHal)
712{
713 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
714
715#ifdef FEATURE_WLAN_DIAG_SUPPORT
716 WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
717
718 vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
719 psRequest.event_subtype = WLAN_START_BMPS_AUTO_TIMER_REQ;
720
721 WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
722#endif
723
724 smsLog(pMac, LOG2, FL("Entering pmcStartAutoBmpsTimer\n"));
725
726 /* Check if BMPS is enabled. */
727 if (!pMac->pmc.bmpsEnabled)
728 {
729 smsLog(pMac, LOGE, "PMC: Cannot enable BMPS timer. BMPS is disabled\n");
730 return eHAL_STATUS_FAILURE;
731 }
732
733 pMac->pmc.autoBmpsEntryEnabled = TRUE;
734
735 /* Check if there is an Infra session. If there is no Infra session, timer will be started
736 when STA associates to AP */
737
738 if (pmcShouldBmpsTimerRun(pMac))
739 {
740 if (pmcStartTrafficTimer(hHal, pMac->pmc.bmpsConfig.trafficMeasurePeriod) != eHAL_STATUS_SUCCESS)
741 return eHAL_STATUS_FAILURE;
742 }
743
744
745
746 return eHAL_STATUS_SUCCESS;
747}
748
749/* ---------------------------------------------------------------------------
750 \fn pmcStopAutoBmpsTimer
751 \brief Stops the Auto BMPS Timer that was started using sme_startAutoBmpsTimer
752 Stopping the timer does not cause a device state change. Only the timer
753 is stopped. If "Full Power" is desired, use the pmcRequestFullPower API
754 \param hHal - The handle returned by macOpen.
755 \return eHalStatus
756 ---------------------------------------------------------------------------*/
757eHalStatus pmcStopAutoBmpsTimer (tHalHandle hHal)
758{
759 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
760
761#ifdef FEATURE_WLAN_DIAG_SUPPORT
762 WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
763
764 vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
765 psRequest.event_subtype = WLAN_STOP_BMPS_AUTO_TIMER_REQ;
766
767 WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
768#endif
769
770 smsLog(pMac, LOG2, FL("Entering pmcStopAutoBmpsTimer\n"));
771
772 pMac->pmc.autoBmpsEntryEnabled = FALSE;
773 /* If uapsd session is not required or HDD has not requested BMPS, stop the auto bmps timer.*/
774 if (!pMac->pmc.uapsdSessionRequired && !pMac->pmc.bmpsRequestedByHdd)
775 pmcStopTrafficTimer(hHal);
776
777 return eHAL_STATUS_SUCCESS;
778}
779
780/******************************************************************************
781*
782* Name: pmcDisablePowerSave
783*
784* Description:
785* Disables one of the power saving modes.
786*
787* Parameters:
788* hHal - HAL handle for device
789* psMode - the power saving mode to disable
790*
791* Returns:
792* eHAL_STATUS_SUCCESS - successfully disabled
793* eHAL_STATUS_FAILURE - not successfully disabled
794*
795******************************************************************************/
796eHalStatus pmcDisablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode)
797{
798 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
799 tSirMacHTMIMOPowerSaveState htMimoPowerSaveState;
800
801#ifdef FEATURE_WLAN_DIAG_SUPPORT
802 WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
803
804 vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
805 psRequest.event_subtype = WLAN_PS_MODE_DISABLE_REQ;
806 psRequest.enable_disable_powersave_mode = psMode;
807
808 WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
809#endif
810
811 smsLog(pMac, LOG2, FL("Entering pmcDisablePowerSave, power save mode %d\n"), psMode);
812
813 /* Disable the specified power saving mode. */
814 switch (psMode)
815 {
816
817 case ePMC_IDLE_MODE_POWER_SAVE:
818 pMac->pmc.impsEnabled = FALSE;
819 break;
820
821 case ePMC_BEACON_MODE_POWER_SAVE:
822 pMac->pmc.bmpsEnabled = FALSE;
823 break;
824
825 case ePMC_SPATIAL_MULTIPLEX_POWER_SAVE:
826 pMac->pmc.smpsEnabled = FALSE;
827
828 /* Turn off SMPS. */
829 htMimoPowerSaveState = eSIR_HT_MIMO_PS_NO_LIMIT;
830 if (pmcSendMessage(hHal, eWNI_PMC_SMPS_STATE_IND, &htMimoPowerSaveState,
831 sizeof(tSirMacHTMIMOPowerSaveState)) != eHAL_STATUS_SUCCESS)
832 return eHAL_STATUS_FAILURE;
833 break;
834
835 case ePMC_UAPSD_MODE_POWER_SAVE:
836 pMac->pmc.uapsdEnabled = FALSE;
837 break;
838
839 case ePMC_STANDBY_MODE_POWER_SAVE:
840 pMac->pmc.standbyEnabled = FALSE;
841 break;
842
843 case ePMC_WOWL_MODE_POWER_SAVE:
844 pMac->pmc.wowlEnabled = FALSE;
845 break;
846
847 default:
848 smsLog(pMac, LOGE, FL("Invalid power save mode %d\n"), psMode);
849 PMC_ABORT;
850 return eHAL_STATUS_FAILURE;
851 }
852
853 return eHAL_STATUS_SUCCESS;
854}
855
856
857/******************************************************************************
858*
859* Name: pmcQueryPowerState
860*
861* Description:
862* Returns the current power state of the device.
863*
864* Parameters:
865* hHal - HAL handle for device
866* pPowerState - pointer to location to return power state
867* pHwWlanSwitchState - pointer to location to return Hardware WLAN
868* Switch state
869* pSwWlanSwitchState - pointer to location to return Software WLAN
870* Switch state
871*
872* Returns:
873* eHAL_STATUS_SUCCESS - power state successfully returned
874* eHAL_STATUS_FAILURE - power state not successfully returned
875*
876******************************************************************************/
877eHalStatus pmcQueryPowerState (tHalHandle hHal, tPmcPowerState *pPowerState,
878 tPmcSwitchState *pHwWlanSwitchState, tPmcSwitchState *pSwWlanSwitchState)
879{
880 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
881
882 smsLog(pMac, LOG2, FL("Entering pmcQueryPowerState\n"));
883
884 /* Return current power state based on PMC state. */
885 if(pPowerState != NULL)
886 {
887 /* Return current power state based on PMC state. */
888 switch (pMac->pmc.pmcState)
889 {
890
891 case FULL_POWER:
892 *pPowerState = ePMC_FULL_POWER;
893 break;
894
895 default:
896 *pPowerState = ePMC_LOW_POWER;
897 break;
898 }
899 }
900
901 /* Return current switch settings. */
902 if(pHwWlanSwitchState != NULL)
903 *pHwWlanSwitchState = pMac->pmc.hwWlanSwitchState;
904 if(pSwWlanSwitchState != NULL)
905 *pSwWlanSwitchState = pMac->pmc.swWlanSwitchState;
906
907 return eHAL_STATUS_SUCCESS;
908}
909
910
911/******************************************************************************
912*
913* Name: pmcIsPowerSaveEnabled
914*
915* Description:
916* Checks if the device is able to enter one of the power save modes.
917* "Able to enter" means the power save mode is enabled for the device
918* and the host is using the correct power source for entry into the
919* power save mode. This routine does not indicate whether the device
920* is actually in the power save mode at a particular point in time.
921*
922* Parameters:
923* hHal - HAL handle for device
924* psMode - the power saving mode
925*
926* Returns:
927* TRUE if device is able to enter the power save mode, FALSE otherwise
928*
929******************************************************************************/
930tANI_BOOLEAN pmcIsPowerSaveEnabled (tHalHandle hHal, tPmcPowerSavingMode psMode)
931{
932 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
933
934 smsLog(pMac, LOG2, FL("Entering pmcIsPowerSaveEnabled, power save mode %d\n"), psMode);
935
936 /* Check ability to enter based on the specified power saving mode. */
937 switch (psMode)
938 {
939
940 case ePMC_IDLE_MODE_POWER_SAVE:
941 return pMac->pmc.impsEnabled && (pMac->pmc.powerSource != AC_POWER || pMac->pmc.impsConfig.enterOnAc);
942
943 case ePMC_BEACON_MODE_POWER_SAVE:
944 return pMac->pmc.bmpsEnabled;
945
946 case ePMC_SPATIAL_MULTIPLEX_POWER_SAVE:
947 return pMac->pmc.smpsEnabled && (pMac->pmc.powerSource != AC_POWER || pMac->pmc.smpsConfig.enterOnAc);
948
949 case ePMC_UAPSD_MODE_POWER_SAVE:
950 return pMac->pmc.uapsdEnabled;
951
952 case ePMC_STANDBY_MODE_POWER_SAVE:
953 return pMac->pmc.standbyEnabled;
954
955 case ePMC_WOWL_MODE_POWER_SAVE:
956 return pMac->pmc.wowlEnabled;
957 break;
958
959 default:
960 smsLog(pMac, LOGE, FL("Invalid power save mode %d\n"), psMode);
961 PMC_ABORT;
962 return FALSE;
963 }
964}
965
966
967/******************************************************************************
968*
969* Name: pmcRequestFullPower
970*
971* Description:
972* Request that the device be brought to full power state.
973*
974* Parameters:
975* hHal - HAL handle for device
976* callbackRoutine - routine to call when device actually achieves full
977* power state if "eHAL_STATUS_PMC_PENDING" is returned
978* callbackContext - value to be passed as parameter to routine specified
979* above
980* fullPowerReason - Reason for requesting full power mode. This is used
981* by PE to decide whether data null should be sent to
982* AP when exiting BMPS mode. Caller should use the
983* eSME_LINK_DISCONNECTED reason if link is disconnected
984* and there is no need to tell the AP that we are going
985* out of power save.
986*
987* Returns:
988* eHAL_STATUS_SUCCESS - device brought to full power state
989* eHAL_STATUS_FAILURE - device cannot be brought to full power state
990* eHAL_STATUS_PMC_PENDING - device is being brought to full power state,
991* callbackRoutine will be called when completed
992*
993******************************************************************************/
994eHalStatus pmcRequestFullPower (tHalHandle hHal, void (*callbackRoutine) (void *callbackContext, eHalStatus status),
995 void *callbackContext, tRequestFullPowerReason fullPowerReason)
996{
997 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
998 tpRequestFullPowerEntry pEntry;
999
1000#ifdef FEATURE_WLAN_DIAG_SUPPORT
1001 WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
1002
1003 vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
1004 psRequest.event_subtype = WLAN_ENTER_FULL_POWER_REQ;
1005 psRequest.full_power_request_reason = fullPowerReason;
1006
1007 WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
1008#endif
1009
1010 smsLog(pMac, LOG2, FL("Entering pmcRequestFullPower"));
1011
1012 if( !PMC_IS_READY(pMac) )
1013 {
1014 smsLog(pMac, LOGE, FL("Requesting Full Power when PMC not ready\n"));
1015 smsLog(pMac, LOGE, FL("pmcReady = %d pmcState = %s\n"),
1016 pMac->pmc.pmcReady, pmcGetPmcStateStr(pMac->pmc.pmcState));
1017 return eHAL_STATUS_FAILURE;
1018 }
1019
1020 /* If HDD is requesting full power, clear any buffered requests for WOWL and BMPS that were
1021 requested by HDD previously */
1022 if(SIR_IS_FULL_POWER_NEEDED_BY_HDD(fullPowerReason))
1023 {
1024 pMac->pmc.bmpsRequestedByHdd = FALSE;
1025 pMac->pmc.wowlModeRequired = FALSE;
1026 }
1027
1028 /* If already in full power, just return. */
1029 if (pMac->pmc.pmcState == FULL_POWER)
1030 return eHAL_STATUS_SUCCESS;
1031
1032 /* If in IMPS State, then cancel the timer. */
1033 if (pMac->pmc.pmcState == IMPS)
1034 if (palTimerStop(pMac->hHdd, pMac->pmc.hImpsTimer) != eHAL_STATUS_SUCCESS)
1035 {
1036 smsLog(pMac, LOGE, FL("Cannot cancel IMPS timer\n"));
1037 return eHAL_STATUS_FAILURE;
1038 }
1039
1040 /* Enter Request Full Power State. */
1041 if (pmcEnterRequestFullPowerState(hHal, fullPowerReason) != eHAL_STATUS_SUCCESS)
1042 return eHAL_STATUS_FAILURE;
1043
1044 /* If able to enter Request Full Power State, then request is pending.
1045 Allocate entry for request full power callback routine list. */
1046 //If caller doesn't need a callback, simply waits up the chip.
1047 if( callbackRoutine )
1048 {
1049 if (palAllocateMemory(pMac->hHdd, (void **)&pEntry, sizeof(tRequestFullPowerEntry)) != eHAL_STATUS_SUCCESS)
1050 {
1051 smsLog(pMac, LOGE, FL("Cannot allocate memory for request full power routine list entry\n"));
1052 PMC_ABORT;
1053 return eHAL_STATUS_FAILURE;
1054 }
1055
1056 /* Store routine and context in entry. */
1057 pEntry->callbackRoutine = callbackRoutine;
1058 pEntry->callbackContext = callbackContext;
1059
1060 /* Add entry to list. */
1061 csrLLInsertTail(&pMac->pmc.requestFullPowerList, &pEntry->link, TRUE);
1062 }
1063
1064 return eHAL_STATUS_PMC_PENDING;
1065}
1066
1067
1068/******************************************************************************
1069*
1070* Name: pmcRequestImps
1071*
1072* Description:
1073* Request that the device be placed in Idle Mode Power Save (IMPS).
1074* The Common Scan/Roam Module makes this request. The device will be
1075* placed into IMPS for the specified amount of time, and then returned
1076* to full power.
1077*
1078* Parameters:
1079* hHal - HAL handle for device
1080* impsPeriod - amount of time to remain in IMPS (milliseconds)
1081* callbackRoutine - routine to call when IMPS period has finished and
1082* the device has been brought to full power
1083* callbackContext - value to be passed as parameter to routine specified
1084* above
1085*
1086* Returns:
1087* eHAL_STATUS_SUCCESS - device will enter IMPS
1088* eHAL_STATUS_PMC_DISABLED - IMPS is disabled
1089* eHAL_STATUS_PMC_NOT_NOW - another module is prohibiting entering IMPS
1090* at this time
1091* eHAL_STATUS_PMC_AC_POWER - IMPS is disabled when host operating from
1092* AC power
1093* eHAL_STATUS_PMC_ALREADY_IN_IMPS - device is already in IMPS
1094* eHAL_STATUS_PMC_SYS_ERROR - system error that prohibits entering IMPS
1095*
1096******************************************************************************/
1097eHalStatus pmcRequestImps (tHalHandle hHal, tANI_U32 impsPeriod,
1098 void (*callbackRoutine) (void *callbackContext, eHalStatus status),
1099 void *callbackContext)
1100{
1101 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1102 eHalStatus status;
1103
1104#ifdef FEATURE_WLAN_DIAG_SUPPORT
1105 WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
1106
1107 vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
1108 psRequest.event_subtype = WLAN_IMPS_ENTER_REQ;
1109 psRequest.imps_period = impsPeriod;
1110
1111 WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
1112#endif
1113
1114
1115 smsLog(pMac, LOG2, FL("Entering pmcRequestImps"));
1116
1117 status = pmcEnterImpsCheck( pMac );
1118 if( HAL_STATUS_SUCCESS( status ) )
1119 {
1120 /* Enter Request IMPS State. */
1121 status = pmcEnterRequestImpsState( hHal );
1122 if (HAL_STATUS_SUCCESS( status ))
1123 {
1124 /* Save the period and callback routine for when we need it. */
1125 pMac->pmc.impsPeriod = impsPeriod;
1126 pMac->pmc.impsCallbackRoutine = callbackRoutine;
1127 pMac->pmc.impsCallbackContext = callbackContext;
1128
1129 }
1130 else
1131 {
1132 status = eHAL_STATUS_PMC_SYS_ERROR;
1133 }
1134 }
1135
1136 return status;
1137}
1138
1139
1140/******************************************************************************
1141*
1142* Name: pmcRegisterPowerSaveCheck
1143*
1144* Description:
1145* Allows a routine to be registered so that the routine is called whenever
1146* the device is about to enter one of the power save modes. This routine
1147* will say whether the device is allowed to enter the power save mode at
1148* the time of the call.
1149*
1150* Parameters:
1151* hHal - HAL handle for device
1152* checkRoutine - routine to call before entering a power save mode, should
1153* return TRUE if the device is allowed to enter the power
1154* save mode, FALSE otherwise
1155* checkContext - value to be passed as parameter to routine specified above
1156*
1157* Returns:
1158* eHAL_STATUS_SUCCESS - successfully registered
1159* eHAL_STATUS_FAILURE - not successfully registered
1160*
1161******************************************************************************/
1162eHalStatus pmcRegisterPowerSaveCheck (tHalHandle hHal, tANI_BOOLEAN (*checkRoutine) (void *checkContext),
1163 void *checkContext)
1164{
1165 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1166 tpPowerSaveCheckEntry pEntry;
1167
1168 smsLog(pMac, LOG2, FL("Entering pmcRegisterPowerSaveCheck"));
1169
1170 /* Allocate entry for power save check routine list. */
1171 if (palAllocateMemory(pMac->hHdd, (void **)&pEntry, sizeof(tPowerSaveCheckEntry)) != eHAL_STATUS_SUCCESS)
1172 {
1173 smsLog(pMac, LOGE, FL("Cannot allocate memory for power save check routine list entry\n"));
1174 PMC_ABORT;
1175 return eHAL_STATUS_FAILURE;
1176 }
1177
1178 /* Store routine and context in entry. */
1179 pEntry->checkRoutine = checkRoutine;
1180 pEntry->checkContext = checkContext;
1181
1182 /* Add entry to list. */
1183 csrLLInsertTail(&pMac->pmc.powerSaveCheckList, &pEntry->link, FALSE);
1184
1185 return eHAL_STATUS_SUCCESS;
1186}
1187
1188
1189/******************************************************************************
1190*
1191* Name: pmcDeregisterPowerSaveCheck
1192*
1193* Description:
1194* Reregisters a routine that was previously registered with
1195* pmcRegisterPowerSaveCheck.
1196*
1197* Parameters:
1198* hHal - HAL handle for device
1199* checkRoutine - routine to deregister
1200*
1201* Returns:
1202* eHAL_STATUS_SUCCESS - successfully deregistered
1203* eHAL_STATUS_FAILURE - not successfully deregistered
1204*
1205******************************************************************************/
1206eHalStatus pmcDeregisterPowerSaveCheck (tHalHandle hHal, tANI_BOOLEAN (*checkRoutine) (void *checkContext))
1207{
1208 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1209 tListElem *pEntry;
1210 tpPowerSaveCheckEntry pPowerSaveCheckEntry;
1211
1212 smsLog(pMac, LOG2, FL("Entering pmcDeregisterPowerSaveCheck"));
1213
1214 /* Find entry in the power save check routine list that matches
1215 the specified routine and remove it. */
1216 pEntry = csrLLPeekHead(&pMac->pmc.powerSaveCheckList, FALSE);
1217 while (pEntry != NULL)
1218 {
1219 pPowerSaveCheckEntry = GET_BASE_ADDR(pEntry, tPowerSaveCheckEntry, link);
1220 if (pPowerSaveCheckEntry->checkRoutine == checkRoutine)
1221 {
1222 if (csrLLRemoveEntry(&pMac->pmc.powerSaveCheckList, pEntry, FALSE))
1223 {
1224 if (palFreeMemory(pMac->hHdd, pPowerSaveCheckEntry) != eHAL_STATUS_SUCCESS)
1225 {
1226 smsLog(pMac, LOGE, FL("Cannot free memory for power save check routine list entry\n"));
1227 PMC_ABORT;
1228 return eHAL_STATUS_FAILURE;
1229 }
1230 }
1231 else
1232 {
1233 smsLog(pMac, LOGE, FL("Cannot remove power save check routine list entry\n"));
1234 return eHAL_STATUS_FAILURE;
1235 }
1236 return eHAL_STATUS_SUCCESS;
1237 }
1238 pEntry = csrLLNext(&pMac->pmc.powerSaveCheckList, pEntry, FALSE);
1239 }
1240
1241 /* Could not find matching entry. */
1242 return eHAL_STATUS_FAILURE;
1243}
1244
1245
1246static void pmcProcessResponse( tpAniSirGlobal pMac, tSirSmeRsp *pMsg )
1247{
1248 tListElem *pEntry = NULL;
1249 tSmeCmd *pCommand = NULL;
1250 tANI_BOOLEAN fRemoveCommand = eANI_BOOLEAN_TRUE;
1251
1252 pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
1253 if(pEntry)
1254 {
1255 pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
1256
1257 smsLog(pMac, LOG1, FL("process message = %d\n"), pMsg->messageType);
1258
1259 /* Process each different type of message. */
1260 switch (pMsg->messageType)
1261 {
1262
1263 /* We got a response to our IMPS request. */
1264 case eWNI_PMC_ENTER_IMPS_RSP:
1265 smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_ENTER_IMPS_RSP with status = %d\n"), pMsg->statusCode);
1266 if( (eSmeCommandEnterImps != pCommand->command) && (eSmeCommandEnterStandby != pCommand->command) )
1267 {
1268 smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_ENTER_IMPS_RSP without request\n"));
1269 fRemoveCommand = eANI_BOOLEAN_FALSE;
1270 break;
1271 }
1272 if(pMac->pmc.pmcState == REQUEST_IMPS)
1273 {
1274 /* Enter IMPS State if response indicates success. */
1275 if (pMsg->statusCode == eSIR_SME_SUCCESS)
1276 {
1277 pmcEnterImpsState(pMac);
1278 }
1279
1280 /* If response is failure, then we stay in Full Power State and tell everyone that we aren't going into IMPS. */
1281 else {
1282 smsLog(pMac, LOGE, FL("Response message to request to enter IMPS indicates failure, status %x\n"),
1283 pMsg->statusCode);
1284 pmcEnterFullPowerState(pMac);
1285 }
1286 }
1287 else if (pMac->pmc.pmcState == REQUEST_STANDBY)
1288 {
1289 /* Enter STANDBY State if response indicates success. */
1290 if (pMsg->statusCode == eSIR_SME_SUCCESS)
1291 {
1292 pmcEnterStandbyState(pMac);
1293 pmcDoStandbyCallbacks(pMac, eHAL_STATUS_SUCCESS);
1294 }
1295
1296 /* If response is failure, then we stay in Full Power State
1297 and tell everyone that we aren't going into STANDBY. */
1298 else
1299 {
1300 smsLog(pMac, LOGE, "PMC: response message to request to enter "
1301 "standby indicates failure, status %x\n", pMsg->statusCode);
1302 pmcEnterFullPowerState(pMac);
1303 pmcDoStandbyCallbacks(pMac, eHAL_STATUS_FAILURE);
1304 }
1305 }
1306 else
1307 {
1308 smsLog(pMac, LOGE, "PMC: Enter IMPS rsp rcvd when device is "
1309 "in %d state\n", pMac->pmc.pmcState);
1310 }
1311 break;
1312
1313 /* We got a response to our wake from IMPS request. */
1314 case eWNI_PMC_EXIT_IMPS_RSP:
1315 smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_EXIT_IMPS_RSP with status = %d\n"), pMsg->statusCode);
1316 if( eSmeCommandExitImps != pCommand->command )
1317 {
1318 smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_EXIT_IMPS_RSP without request\n"));
1319 fRemoveCommand = eANI_BOOLEAN_FALSE;
1320 break;
1321 }
1322 /* Check that we are in the correct state for this message. */
1323 if (pMac->pmc.pmcState != REQUEST_FULL_POWER)
1324 {
1325 smsLog(pMac, LOGE, FL("Got Exit IMPS Response Message while in state %d\n"), pMac->pmc.pmcState);
1326 break;
1327 }
1328
1329 /* Enter Full Power State. */
1330 if (pMsg->statusCode != eSIR_SME_SUCCESS)
1331 {
1332 smsLog(pMac, LOGP, FL("Response message to request to exit IMPS indicates failure, status %x\n"),
1333 pMsg->statusCode);
1334 }
1335 pmcEnterFullPowerState(pMac);
1336 break;
1337
1338 /* We got a response to our BMPS request. */
1339 case eWNI_PMC_ENTER_BMPS_RSP:
1340 smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_ENTER_BMPS_RSP with status = %d\n"), pMsg->statusCode);
1341 if( eSmeCommandEnterBmps != pCommand->command )
1342 {
1343 smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_ENTER_BMPS_RSP without request\n"));
1344 fRemoveCommand = eANI_BOOLEAN_FALSE;
1345 break;
1346 }
1347 pMac->pmc.bmpsRequestQueued = eANI_BOOLEAN_FALSE;
1348 /* Check that we are in the correct state for this message. */
1349 if (pMac->pmc.pmcState != REQUEST_BMPS)
1350 {
1351 smsLog(pMac, LOGE, FL("Got Enter BMPS Response Message while in state %d\n"), pMac->pmc.pmcState);
1352 break;
1353 }
1354
1355 /* Enter BMPS State if response indicates success. */
1356 if (pMsg->statusCode == eSIR_SME_SUCCESS)
1357 {
1358 pmcEnterBmpsState(pMac);
1359 /* Note: If BMPS was requested because of start UAPSD,
1360 there will no entries for BMPS callback routines and
1361 pmcDoBmpsCallbacks will be a No-Op*/
1362 pmcDoBmpsCallbacks(pMac, eHAL_STATUS_SUCCESS);
1363 }
1364 /* If response is failure, then we stay in Full Power State and tell everyone that we aren't going into BMPS. */
1365 else
1366 {
1367 smsLog(pMac, LOGE, FL("Response message to request to enter BMPS indicates failure, status %x\n"),
1368 pMsg->statusCode);
1369 pmcEnterFullPowerState(pMac);
1370 //Do not call UAPSD callback here since it may be re-entered
1371 pmcDoBmpsCallbacks(pMac, eHAL_STATUS_FAILURE);
1372 }
1373 break;
1374
1375 /* We got a response to our wake from BMPS request. */
1376 case eWNI_PMC_EXIT_BMPS_RSP:
1377 smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_EXIT_BMPS_RSP with status = %d\n"), pMsg->statusCode);
1378 if( eSmeCommandExitBmps != pCommand->command )
1379 {
1380 smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_EXIT_BMPS_RSP without request\n"));
1381 fRemoveCommand = eANI_BOOLEAN_FALSE;
1382 break;
1383 }
1384 /* Check that we are in the correct state for this message. */
1385 if (pMac->pmc.pmcState != REQUEST_FULL_POWER)
1386 {
1387 smsLog(pMac, LOGE, FL("Got Exit BMPS Response Message while in state %d\n"), pMac->pmc.pmcState);
1388 break;
1389 }
1390
1391 /* Enter Full Power State. */
1392 if (pMsg->statusCode != eSIR_SME_SUCCESS)
1393 {
1394 smsLog(pMac, LOGP, FL("Response message to request to exit BMPS indicates failure, status %x\n"),
1395 pMsg->statusCode);
1396 }
1397 pmcEnterFullPowerState(pMac);
1398 break;
1399
1400 /* We got a response to our Start UAPSD request. */
1401 case eWNI_PMC_ENTER_UAPSD_RSP:
1402 smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_ENTER_UAPSD_RSP with status = %d\n"), pMsg->statusCode);
1403 if( eSmeCommandEnterUapsd != pCommand->command )
1404 {
1405 smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_ENTER_UAPSD_RSP without request\n"));
1406 fRemoveCommand = eANI_BOOLEAN_FALSE;
1407 break;
1408 }
1409 /* Check that we are in the correct state for this message. */
1410 if (pMac->pmc.pmcState != REQUEST_START_UAPSD)
1411 {
1412 smsLog(pMac, LOGE, FL("Got Enter Uapsd rsp Message while in state %d\n"), pMac->pmc.pmcState);
1413 break;
1414 }
1415
1416 /* Enter UAPSD State if response indicates success. */
1417 if (pMsg->statusCode == eSIR_SME_SUCCESS)
1418 {
1419 pmcEnterUapsdState(pMac);
1420 pmcDoStartUapsdCallbacks(pMac, eHAL_STATUS_SUCCESS);
1421 }
1422 /* If response is failure, then we try to put the chip back in
1423 BMPS mode*/
1424 else {
1425 smsLog(pMac, LOGE, "PMC: response message to request to enter "
1426 "UAPSD indicates failure, status %x\n", pMsg->statusCode);
1427 //Need to reset the UAPSD flag so pmcEnterBmpsState won't try to enter UAPSD.
1428 pMac->pmc.uapsdSessionRequired = FALSE;
1429 pmcEnterBmpsState(pMac);
1430 //UAPSD will not be retied in this case so tell requester we are done with failure
1431 pmcDoStartUapsdCallbacks(pMac, eHAL_STATUS_FAILURE);
1432 }
1433 break;
1434
1435 /* We got a response to our Stop UAPSD request. */
1436 case eWNI_PMC_EXIT_UAPSD_RSP:
1437 smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_EXIT_UAPSD_RSP with status = %d\n"), pMsg->statusCode);
1438 if( eSmeCommandExitUapsd != pCommand->command )
1439 {
1440 smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_EXIT_UAPSD_RSP without request\n"));
1441 fRemoveCommand = eANI_BOOLEAN_FALSE;
1442 break;
1443 }
1444 /* Check that we are in the correct state for this message. */
1445 if (pMac->pmc.pmcState != REQUEST_STOP_UAPSD)
1446 {
1447 smsLog(pMac, LOGE, FL("Got Exit Uapsd rsp Message while in state %d\n"), pMac->pmc.pmcState);
1448 break;
1449 }
1450
1451 /* Enter BMPS State */
1452 if (pMsg->statusCode != eSIR_SME_SUCCESS) {
1453 smsLog(pMac, LOGP, "PMC: response message to request to exit "
1454 "UAPSD indicates failure, status %x\n", pMsg->statusCode);
1455 }
1456 pmcEnterBmpsState(pMac);
1457 break;
1458
1459 /* We got a response to our enter WOWL request. */
1460 case eWNI_PMC_ENTER_WOWL_RSP:
1461
1462 if( eSmeCommandEnterWowl != pCommand->command )
1463 {
1464 smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_ENTER_WOWL_RSP without request\n"));
1465 fRemoveCommand = eANI_BOOLEAN_FALSE;
1466 break;
1467 }
1468 /* Check that we are in the correct state for this message. */
1469 if (pMac->pmc.pmcState != REQUEST_ENTER_WOWL)
1470 {
1471 smsLog(pMac, LOGE, FL("Got eWNI_PMC_ENTER_WOWL_RSP while in state %s\n"),
1472 pmcGetPmcStateStr(pMac->pmc.pmcState));
1473 break;
1474 }
1475
1476 /* Enter WOWL State if response indicates success. */
1477 if (pMsg->statusCode == eSIR_SME_SUCCESS) {
1478 pmcEnterWowlState(pMac);
1479 pmcDoEnterWowlCallbacks(pMac, eHAL_STATUS_SUCCESS);
1480 }
1481
1482 /* If response is failure, then we try to put the chip back in
1483 BMPS mode*/
1484 else {
1485 smsLog(pMac, LOGE, "PMC: response message to request to enter "
1486 "WOWL indicates failure, status %x\n", pMsg->statusCode);
1487 pmcEnterBmpsState(pMac);
1488 pmcDoEnterWowlCallbacks(pMac, eHAL_STATUS_FAILURE);
1489 }
1490 break;
1491
1492 /* We got a response to our exit WOWL request. */
1493 case eWNI_PMC_EXIT_WOWL_RSP:
1494
1495 if( eSmeCommandExitWowl != pCommand->command )
1496 {
1497 smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_EXIT_WOWL_RSP without request\n"));
1498 fRemoveCommand = eANI_BOOLEAN_FALSE;
1499 break;
1500 }
1501 /* Check that we are in the correct state for this message. */
1502 if (pMac->pmc.pmcState != REQUEST_EXIT_WOWL)
1503 {
1504 smsLog(pMac, LOGE, FL("Got Exit WOWL rsp Message while in state %d\n"), pMac->pmc.pmcState);
1505 break;
1506 }
1507
1508 /* Enter BMPS State */
1509 if (pMsg->statusCode != eSIR_SME_SUCCESS) {
1510 smsLog(pMac, LOGP, "PMC: response message to request to exit "
1511 "WOWL indicates failure, status %x\n", pMsg->statusCode);
1512 }
1513 pmcEnterBmpsState(pMac);
1514 break;
1515
1516 default:
1517 smsLog(pMac, LOGE, FL("Invalid message type %d received\n"), pMsg->messageType);
1518 PMC_ABORT;
1519 break;
1520 }//switch
1521
1522 if( fRemoveCommand )
1523 {
1524 if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ) )
1525 {
1526 pmcReleaseCommand( pMac, pCommand );
1527 smeProcessPendingQueue( pMac );
1528 }
1529 }
1530 }
1531 else
1532 {
1533 smsLog(pMac, LOGE, FL("message type %d received but no request is found\n"), pMsg->messageType);
1534 }
1535}
1536
1537
1538/******************************************************************************
1539*
1540* Name: pmcMessageProcessor
1541*
1542* Description:
1543* Process a message received by PMC.
1544*
1545* Parameters:
1546* hHal - HAL handle for device
1547* pMsg - pointer to received message
1548*
1549* Returns:
1550* nothing
1551*
1552******************************************************************************/
1553void pmcMessageProcessor (tHalHandle hHal, tSirSmeRsp *pMsg)
1554{
1555 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1556
1557 smsLog(pMac, LOG2, FL("Entering pmcMessageProcessor, message type %d\n"), pMsg->messageType);
1558
1559 switch( pMsg->messageType )
1560 {
1561 case eWNI_PMC_EXIT_BMPS_IND:
1562 //When PMC needs to handle more indication from PE, they need to be added here.
1563 {
1564 /* Device left BMPS on its own. */
1565 smsLog(pMac, LOGW, FL("Rcvd eWNI_PMC_EXIT_BMPS_IND with status = %d\n"), pMsg->statusCode);
1566 /* Check that we are in the correct state for this message. */
1567 switch(pMac->pmc.pmcState)
1568 {
1569 case BMPS:
1570 case REQUEST_START_UAPSD:
1571 case UAPSD:
1572 case REQUEST_STOP_UAPSD:
1573 case REQUEST_ENTER_WOWL:
1574 case WOWL:
1575 case REQUEST_EXIT_WOWL:
1576 case REQUEST_FULL_POWER:
1577 smsLog(pMac, LOGW, FL("Got eWNI_PMC_EXIT_BMPS_IND while in state %d\n"), pMac->pmc.pmcState);
1578 break;
1579 default:
1580 smsLog(pMac, LOGE, FL("Got eWNI_PMC_EXIT_BMPS_IND while in state %d\n"), pMac->pmc.pmcState);
1581 PMC_ABORT;
1582 break;
1583 }
1584
1585 /* Enter Full Power State. */
1586 if (pMsg->statusCode != eSIR_SME_SUCCESS)
1587 {
1588 smsLog(pMac, LOGP, FL("Exit BMPS indication indicates failure, status %x\n"), pMsg->statusCode);
1589 }
1590 else
1591 {
1592 tpSirSmeExitBmpsInd pExitBmpsInd = (tpSirSmeExitBmpsInd)pMsg;
1593 pmcEnterRequestFullPowerState(hHal, pExitBmpsInd->exitBmpsReason);
1594 }
1595 break;
1596 }
1597
1598 default:
1599 pmcProcessResponse( pMac, pMsg );
1600 break;
1601 }
1602
1603}
1604
1605
1606tANI_BOOLEAN pmcValidateConnectState( tHalHandle hHal )
1607{
1608 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1609
1610 if ( !csrIsInfraConnected( pMac ) )
1611 {
1612 smsLog(pMac, LOGW, "PMC: STA not associated. BMPS cannot be entered\n");
1613 return eANI_BOOLEAN_FALSE;
1614 }
1615
1616 //Cannot have other session
1617 if ( csrIsIBSSStarted( pMac ) )
1618 {
1619 smsLog(pMac, LOGW, "PMC: IBSS started. BMPS cannot be entered\n");
1620 return eANI_BOOLEAN_FALSE;
1621 }
1622 if ( csrIsBTAMPStarted( pMac ) )
1623 {
1624 smsLog(pMac, LOGW, "PMC: BT-AMP exists. BMPS cannot be entered\n");
1625 return eANI_BOOLEAN_FALSE;
1626 }
Jeff Johnsone7245742012-09-05 17:12:55 -07001627 if ((vos_concurrent_sessions_running()) &&
1628 (csrIsConcurrentInfraConnected( pMac ) ||
1629 (vos_get_concurrency_mode()& VOS_SAP) ||
1630 (vos_get_concurrency_mode()& VOS_P2P_GO)))
Jeff Johnson295189b2012-06-20 16:38:30 -07001631 {
1632 smsLog(pMac, LOGW, "PMC: Multiple active sessions exists. BMPS cannot be entered\n");
1633 return eANI_BOOLEAN_FALSE;
1634 }
1635 return eANI_BOOLEAN_TRUE;
1636}
1637
1638tANI_BOOLEAN pmcAllowImps( tHalHandle hHal )
1639{
1640 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1641
1642 //Cannot have other session like IBSS or BT AMP running
1643 if ( csrIsIBSSStarted( pMac ) )
1644 {
1645 smsLog(pMac, LOGW, "PMC: IBSS started. IMPS cannot be entered\n");
1646 return eANI_BOOLEAN_FALSE;
1647 }
1648 if ( csrIsBTAMPStarted( pMac ) )
1649 {
1650 smsLog(pMac, LOGW, "PMC: BT-AMP exists. IMPS cannot be entered\n");
1651 return eANI_BOOLEAN_FALSE;
1652 }
1653
1654 //All sessions must be disconnected to allow IMPS
1655 if ( !csrIsAllSessionDisconnected( pMac ) )
1656 {
1657 smsLog(pMac, LOGW, "PMC: Atleast one connected session. IMPS cannot be entered\n");
1658 return eANI_BOOLEAN_FALSE;
1659 }
1660
1661 return eANI_BOOLEAN_TRUE;
1662}
1663
1664/******************************************************************************
1665*
1666* Name: pmcRequestBmps
1667*
1668* Description:
1669* Request that the device be put in BMPS state.
1670*
1671* Parameters:
1672* hHal - HAL handle for device
1673* callbackRoutine - Callback routine invoked in case of success/failure
1674* callbackContext - value to be passed as parameter to routine specified
1675* above
1676*
1677* Returns:
1678* eHAL_STATUS_SUCCESS - device is in BMPS state
1679* eHAL_STATUS_FAILURE - device cannot be brought to BMPS state
1680* eHAL_STATUS_PMC_PENDING - device is being brought to BMPS state,
1681*
1682******************************************************************************/
1683eHalStatus pmcRequestBmps (
1684 tHalHandle hHal,
1685 void (*callbackRoutine) (void *callbackContext, eHalStatus status),
1686 void *callbackContext)
1687{
1688 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1689 tpRequestBmpsEntry pEntry;
1690 eHalStatus status;
1691
1692#ifdef FEATURE_WLAN_DIAG_SUPPORT
1693 WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
1694
1695 vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
1696 psRequest.event_subtype = WLAN_BMPS_ENTER_REQ;
1697
1698 WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
1699#endif
1700
1701 smsLog(pMac, LOG2, "PMC: entering pmcRequestBmps");
1702
1703 /* If already in BMPS, just return. */
1704 if (pMac->pmc.pmcState == BMPS || REQUEST_START_UAPSD == pMac->pmc.pmcState || UAPSD == pMac->pmc.pmcState)
1705 {
1706 smsLog(pMac, LOG2, "PMC: Device already in BMPS pmcState %d", pMac->pmc.pmcState);
1707 pMac->pmc.bmpsRequestedByHdd = TRUE;
1708 return eHAL_STATUS_SUCCESS;
1709 }
1710
1711 status = pmcEnterBmpsCheck( pMac );
1712 if(HAL_STATUS_SUCCESS( status ))
1713 {
1714 status = pmcEnterRequestBmpsState(hHal);
1715 /* Enter Request BMPS State. */
1716 if ( HAL_STATUS_SUCCESS( status ) )
1717 {
1718 /* Remember that HDD requested BMPS. This flag will be used to put the
1719 device back into BMPS if any module other than HDD (e.g. CSR, QoS, or BAP)
1720 requests full power for any reason */
1721 pMac->pmc.bmpsRequestedByHdd = TRUE;
1722
1723 /* If able to enter Request BMPS State, then request is pending.
1724 Allocate entry for request BMPS callback routine list. */
1725 if (palAllocateMemory(
1726 pMac->hHdd, (void **)&pEntry,
1727 sizeof(tRequestBmpsEntry)) != eHAL_STATUS_SUCCESS)
1728 {
1729 smsLog(pMac, LOGE, "PMC: cannot allocate memory for request "
1730 "BMPS routine list entry\n");
1731 return eHAL_STATUS_FAILURE;
1732 }
1733
1734 /* Store routine and context in entry. */
1735 pEntry->callbackRoutine = callbackRoutine;
1736 pEntry->callbackContext = callbackContext;
1737
1738 /* Add entry to list. */
1739 csrLLInsertTail(&pMac->pmc.requestBmpsList, &pEntry->link, FALSE);
1740
1741 status = eHAL_STATUS_PMC_PENDING;
1742 }
1743 else
1744 {
1745 status = eHAL_STATUS_FAILURE;
1746 }
1747 }
1748
1749 return status;
1750}
1751
1752/******************************************************************************
1753*
1754* Name: pmcStartUapsd
1755*
1756* Description:
1757* Request that the device be put in UAPSD state.
1758*
1759* Parameters:
1760* hHal - HAL handle for device
1761* callbackRoutine - Callback routine invoked in case of success/failure
1762* callbackContext - value to be passed as parameter to routine specified
1763* above
1764*
1765* Returns:
1766* eHAL_STATUS_SUCCESS - device is in UAPSD state
1767* eHAL_STATUS_FAILURE - device cannot be brought to UAPSD state
1768* eHAL_STATUS_PMC_PENDING - device is being brought to UAPSD state
1769* eHAL_STATUS_PMC_DISABLED - UAPSD is disabled or BMPS mode is disabled
1770*
1771******************************************************************************/
1772eHalStatus pmcStartUapsd (
1773 tHalHandle hHal,
1774 void (*callbackRoutine) (void *callbackContext, eHalStatus status),
1775 void *callbackContext)
1776{
1777 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1778 tpStartUapsdEntry pEntry;
1779
1780#ifdef FEATURE_WLAN_DIAG_SUPPORT
1781 WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
1782
1783 vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
1784 psRequest.event_subtype = WLAN_UAPSD_START_REQ;
1785
1786 WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
1787#endif
1788
1789 smsLog(pMac, LOG2, "PMC: entering pmcStartUapsd");
1790
1791 if( !PMC_IS_READY(pMac) )
1792 {
1793 smsLog(pMac, LOGE, FL("Requesting UAPSD when PMC not ready\n"));
1794 smsLog(pMac, LOGE, FL("pmcReady = %d pmcState = %s\n"),
1795 pMac->pmc.pmcReady, pmcGetPmcStateStr(pMac->pmc.pmcState));
1796 return eHAL_STATUS_FAILURE;
1797 }
1798
1799 /* Check if BMPS is enabled. */
1800 if (!pMac->pmc.bmpsEnabled)
1801 {
1802 smsLog(pMac, LOGE, "PMC: Cannot enter UAPSD. BMPS is disabled\n");
1803 return eHAL_STATUS_PMC_DISABLED;
1804 }
1805
1806 /* Check if UAPSD is enabled. */
1807 if (!pMac->pmc.uapsdEnabled)
1808 {
1809 smsLog(pMac, LOGE, "PMC: Cannot enter UAPSD. UAPSD is disabled\n");
1810 return eHAL_STATUS_PMC_DISABLED;
1811 }
1812
1813 /* If already in UAPSD, just return. */
1814 if (pMac->pmc.pmcState == UAPSD)
1815 return eHAL_STATUS_SUCCESS;
1816
1817 /* Check that we are associated. */
1818 if (!pmcValidateConnectState( pMac ))
1819 {
1820 smsLog(pMac, LOGE, "PMC: STA not associated with an AP. UAPSD cannot be entered\n");
1821 return eHAL_STATUS_FAILURE;
1822 }
1823
1824 /* Enter REQUEST_START_UAPSD State. */
1825 if (pmcEnterRequestStartUapsdState(hHal) != eHAL_STATUS_SUCCESS)
1826 return eHAL_STATUS_FAILURE;
1827
1828 if( NULL != callbackRoutine )
1829 {
1830 /* If success then request is pending. Allocate entry for callback routine list. */
1831 if (palAllocateMemory(pMac->hHdd, (void **)&pEntry,
1832 sizeof(tStartUapsdEntry)) != eHAL_STATUS_SUCCESS)
1833 {
1834 smsLog(pMac, LOGE, "PMC: cannot allocate memory for request "
1835 "start UAPSD routine list entry\n");
1836 return eHAL_STATUS_FAILURE;
1837 }
1838
1839 /* Store routine and context in entry. */
1840 pEntry->callbackRoutine = callbackRoutine;
1841 pEntry->callbackContext = callbackContext;
1842
1843 /* Add entry to list. */
1844 csrLLInsertTail(&pMac->pmc.requestStartUapsdList, &pEntry->link, FALSE);
1845 }
1846
1847 return eHAL_STATUS_PMC_PENDING;
1848}
1849
1850/******************************************************************************
1851*
1852* Name: pmcStopUapsd
1853*
1854* Description:
1855* Request that the device be put out of UAPSD state.
1856*
1857* Parameters:
1858* hHal - HAL handle for device
1859*
1860* Returns:
1861* eHAL_STATUS_SUCCESS - device is put out of UAPSD and back in BMPS state
1862* eHAL_STATUS_FAILURE - device cannot be brought out of UAPSD state
1863*
1864******************************************************************************/
1865eHalStatus pmcStopUapsd (tHalHandle hHal)
1866{
1867 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1868
1869#ifdef FEATURE_WLAN_DIAG_SUPPORT
1870 WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
1871
1872 vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
1873 psRequest.event_subtype = WLAN_UAPSD_STOP_REQ;
1874
1875 WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
1876#endif
1877
1878 smsLog(pMac, LOG2, "PMC: entering pmcStopUapsd");
1879
1880 /* Clear any buffered command for entering UAPSD */
1881 pMac->pmc.uapsdSessionRequired = FALSE;
1882
1883 /* Nothing to be done if we are already out of UAPSD. This can happen if
1884 some other module (HDD, BT-AMP) requested Full Power.*/
1885 if (pMac->pmc.pmcState != UAPSD && pMac->pmc.pmcState != REQUEST_STOP_UAPSD)
1886 {
1887 smsLog(pMac, LOGW, "PMC: Device is already out of UAPSD "
1888 "state. Current state is %d\n", pMac->pmc.pmcState);
1889 return eHAL_STATUS_SUCCESS;
1890 }
1891
1892 /* Enter REQUEST_STOP_UAPSD State*/
1893 if (pmcEnterRequestStopUapsdState(hHal) != eHAL_STATUS_SUCCESS)
1894 return eHAL_STATUS_FAILURE;
1895
1896 return eHAL_STATUS_SUCCESS;
1897}
1898
1899/* ---------------------------------------------------------------------------
1900 \fn pmcRequestStandby
1901 \brief Request that the device be put in standby.
1902 \param hHal - The handle returned by macOpen.
1903 \param callbackRoutine - Callback routine invoked in case of success/failure
1904 \param callbackContext - value to be passed as parameter to callback
1905 \return eHalStatus
1906 eHAL_STATUS_SUCCESS - device is in Standby mode
1907 eHAL_STATUS_FAILURE - device cannot be put in standby mode
1908 eHAL_STATUS_PMC_PENDING - device is being put in standby mode
1909 ---------------------------------------------------------------------------*/
1910extern eHalStatus pmcRequestStandby (
1911 tHalHandle hHal,
1912 void (*callbackRoutine) (void *callbackContext, eHalStatus status),
1913 void *callbackContext)
1914{
1915 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1916
1917#ifdef FEATURE_WLAN_DIAG_SUPPORT
1918 WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type);
1919
1920 vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type));
1921 psRequest.event_subtype = WLAN_ENTER_STANDBY_REQ;
1922
1923 WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC);
1924#endif
1925
1926 smsLog(pMac, LOG2, "PMC: entering pmcRequestStandby");
1927
1928 /* Check if standby is enabled. */
1929 if (!pMac->pmc.standbyEnabled)
1930 {
1931 smsLog(pMac, LOGE, "PMC: Cannot enter standby. Standby is disabled\n");
1932 return eHAL_STATUS_PMC_DISABLED;
1933 }
1934
1935 if( !PMC_IS_READY(pMac) )
1936 {
1937 smsLog(pMac, LOGE, FL("Requesting standby when PMC not ready\n"));
1938 smsLog(pMac, LOGE, FL("pmcReady = %d pmcState = %s\n"),
1939 pMac->pmc.pmcReady, pmcGetPmcStateStr(pMac->pmc.pmcState));
1940 return eHAL_STATUS_FAILURE;
1941 }
1942
1943 /* If already in STANDBY, just return. */
1944 if (pMac->pmc.pmcState == STANDBY)
1945 return eHAL_STATUS_SUCCESS;
1946
1947
1948 if (csrIsIBSSStarted(pMac) || csrIsBTAMPStarted(pMac))
1949 {
1950 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
1951 "WLAN: IBSS or BT-AMP session present. Cannot honor standby request");
1952 return eHAL_STATUS_PMC_NOT_NOW;
1953 }
1954
1955 /* Enter Request Standby State. */
1956 if (pmcEnterRequestStandbyState(hHal) != eHAL_STATUS_SUCCESS)
1957 return eHAL_STATUS_FAILURE;
1958
1959 /* Save the callback routine for when we need it. */
1960 pMac->pmc.standbyCallbackRoutine = callbackRoutine;
1961 pMac->pmc.standbyCallbackContext = callbackContext;
1962
1963 return eHAL_STATUS_PMC_PENDING;
1964}
1965
1966/* ---------------------------------------------------------------------------
1967 \fn pmcRegisterDeviceStateUpdateInd
1968 \brief Register a callback routine that is called whenever
1969 the device enters a new device state (Full Power, BMPS, UAPSD)
1970 \param hHal - The handle returned by macOpen.
1971 \param callbackRoutine - Callback routine to be registered
1972 \param callbackContext - Cookie to be passed back during callback
1973 \return eHalStatus
1974 eHAL_STATUS_SUCCESS - successfully registered
1975 eHAL_STATUS_FAILURE - not successfully registered
1976 ---------------------------------------------------------------------------*/
1977extern eHalStatus pmcRegisterDeviceStateUpdateInd (tHalHandle hHal,
1978 void (*callbackRoutine) (void *callbackContext, tPmcState pmcState),
1979 void *callbackContext)
1980{
1981
1982 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
1983 tpDeviceStateUpdateIndEntry pEntry;
1984
1985 smsLog(pMac, LOG2, FL("Entering pmcRegisterDeviceStateUpdateInd"));
1986
1987 /* Allocate entry for device power state update indication. */
1988 if (palAllocateMemory(pMac->hHdd, (void **)&pEntry, sizeof(tDeviceStateUpdateIndEntry)) != eHAL_STATUS_SUCCESS)
1989 {
1990 smsLog(pMac, LOGE, FL("Cannot allocate memory for device power state update indication\n"));
1991 PMC_ABORT;
1992 return eHAL_STATUS_FAILURE;
1993 }
1994
1995 /* Store routine in entry. */
1996 pEntry->callbackRoutine = callbackRoutine;
1997 pEntry->callbackContext = callbackContext;
1998
1999 /* Add entry to list. */
2000 csrLLInsertTail(&pMac->pmc.deviceStateUpdateIndList, &pEntry->link, FALSE);
2001
2002 return eHAL_STATUS_SUCCESS;
2003}
2004
2005/* ---------------------------------------------------------------------------
2006 \fn pmcDeregisterDeviceStateUpdateInd
2007 \brief Deregister a routine that was registered for device state changes
2008 \param hHal - The handle returned by macOpen.
2009 \param callbackRoutine - Callback routine to be deregistered
2010 \return eHalStatus
2011 eHAL_STATUS_SUCCESS - successfully deregistered
2012 eHAL_STATUS_FAILURE - not successfully deregistered
2013 ---------------------------------------------------------------------------*/
2014eHalStatus pmcDeregisterDeviceStateUpdateInd (tHalHandle hHal,
2015 void (*callbackRoutine) (void *callbackContext, tPmcState pmcState))
2016{
2017 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
2018 tListElem *pEntry;
2019 tpDeviceStateUpdateIndEntry pDeviceStateUpdateIndEntry;
2020
2021 smsLog(pMac, LOG2, FL("Entering pmcDeregisterDeviceStateUpdateInd"));
2022
2023 /* Find entry in the power save update routine list that matches
2024 the specified routine and remove it. */
2025 pEntry = csrLLPeekHead(&pMac->pmc.deviceStateUpdateIndList, FALSE);
2026 while (pEntry != NULL)
2027 {
2028 pDeviceStateUpdateIndEntry = GET_BASE_ADDR(pEntry, tDeviceStateUpdateIndEntry, link);
2029 if (pDeviceStateUpdateIndEntry->callbackRoutine == callbackRoutine)
2030 {
2031 if (!csrLLRemoveEntry(&pMac->pmc.deviceStateUpdateIndList, pEntry, FALSE))
2032 {
2033 smsLog(pMac, LOGE, FL("Cannot remove device state update ind entry from list\n"));
2034 return eHAL_STATUS_FAILURE;
2035 }
2036 if (palFreeMemory(pMac->hHdd, pDeviceStateUpdateIndEntry) != eHAL_STATUS_SUCCESS)
2037 {
2038 smsLog(pMac, LOGE, FL("Cannot free memory for device state update ind routine list entry\n"));
2039 PMC_ABORT;
2040 return eHAL_STATUS_FAILURE;
2041 }
2042 return eHAL_STATUS_SUCCESS;
2043 }
2044 pEntry = csrLLNext(&pMac->pmc.deviceStateUpdateIndList, pEntry, FALSE);
2045 }
2046
2047 /* Could not find matching entry. */
2048 return eHAL_STATUS_FAILURE;
2049}
2050
2051/* ---------------------------------------------------------------------------
2052 \fn pmcReady
2053 \brief fn to inform PMC that eWNI_SME_SYS_READY_IND has been sent to PE.
2054 This acts as a trigger to send a message to PE to update the power
2055 save related conig to FW. Note that if HDD configures any power save
2056 related stuff before this API is invoked, PMC will buffer all the
2057 configutaion.
2058 \param hHal - The handle returned by macOpen.
2059 \return eHalStatus
2060 ---------------------------------------------------------------------------*/
2061eHalStatus pmcReady(tHalHandle hHal)
2062{
2063 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
2064
2065 smsLog(pMac, LOG2, FL("Entering pmcReady"));
2066
2067 if(pMac->pmc.pmcState == STOPPED)
2068 {
2069 smsLog(pMac, LOGP, FL("pmcReady is invoked even before pmcStart"));
2070 return eHAL_STATUS_FAILURE;
2071 }
2072
2073 pMac->pmc.pmcReady = TRUE;
2074 if (pmcSendPowerSaveConfigMessage(hHal) != eHAL_STATUS_SUCCESS)
2075 {
2076 return eHAL_STATUS_FAILURE;
2077 }
2078
2079 return eHAL_STATUS_SUCCESS;
2080}
2081
2082/* ---------------------------------------------------------------------------
2083 \fn pmcWowlAddBcastPattern
2084 \brief Add a pattern for Pattern Byte Matching in Wowl mode. Firmware will
2085 do a pattern match on these patterns when Wowl is enabled during BMPS
2086 mode. Note that Firmware performs the pattern matching only on
2087 broadcast frames and while Libra is in BMPS mode.
2088 \param hHal - The handle returned by macOpen.
2089 \param pattern - Pointer to the pattern to be added
2090 \return eHalStatus
2091 eHAL_STATUS_FAILURE Cannot add pattern
2092 eHAL_STATUS_SUCCESS Request accepted.
2093 ---------------------------------------------------------------------------*/
2094eHalStatus pmcWowlAddBcastPattern (
2095 tHalHandle hHal,
2096 tpSirWowlAddBcastPtrn pattern)
2097{
2098 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
2099
2100#ifdef FEATURE_WLAN_DIAG_SUPPORT
2101 vos_log_powersave_wow_add_ptrn_pkt_type *log_ptr = NULL;
2102 WLAN_VOS_DIAG_LOG_ALLOC(log_ptr, vos_log_powersave_wow_add_ptrn_pkt_type, LOG_WLAN_POWERSAVE_WOW_ADD_PTRN_C);
2103#endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT
2104
2105 smsLog(pMac, LOG2, "PMC: entering pmcWowlAddBcastPattern");
2106
2107 if(pattern == NULL)
2108 {
2109 smsLog(pMac, LOGE, FL("Null broadcast pattern being passed\n"));
2110 return eHAL_STATUS_FAILURE;
2111 }
2112
2113#ifdef FEATURE_WLAN_DIAG_SUPPORT
2114 if( log_ptr )
2115 {
2116 log_ptr->pattern_id = pattern->ucPatternId;
2117 log_ptr->pattern_byte_offset = pattern->ucPatternByteOffset;
2118 log_ptr->pattern_size = pattern->ucPatternSize;
2119 log_ptr->pattern_mask_size = pattern->ucPatternMaskSize;
2120
2121 vos_mem_copy(log_ptr->pattern, pattern->ucPattern, SIR_WOWL_BCAST_PATTERN_MAX_SIZE);
2122 /* 1 bit in the pattern mask denotes 1 byte of pattern hence pattern mask size is 1/8 */
2123 vos_mem_copy(log_ptr->pattern_mask, pattern->ucPatternMask, SIR_WOWL_BCAST_PATTERN_MAX_SIZE >> 3);
2124 }
2125
2126 WLAN_VOS_DIAG_LOG_REPORT(log_ptr);
2127#endif
2128
2129
2130 if(pattern->ucPatternId >= SIR_WOWL_BCAST_MAX_NUM_PATTERNS )
2131 {
2132 smsLog(pMac, LOGE, FL("Pattern Id must range from 0 to %d\n"), SIR_WOWL_BCAST_MAX_NUM_PATTERNS-1);
2133 return eHAL_STATUS_FAILURE;
2134 }
2135
2136 if( pMac->pmc.pmcState == STANDBY || pMac->pmc.pmcState == REQUEST_STANDBY )
2137 {
2138 smsLog(pMac, LOGE, FL("Cannot add WoWL Pattern as chip is in %s state\n"),
2139 pmcGetPmcStateStr(pMac->pmc.pmcState));
2140 return eHAL_STATUS_FAILURE;
2141 }
2142 if( pMac->pmc.pmcState == IMPS || pMac->pmc.pmcState == REQUEST_IMPS )
2143 {
2144 //Wake up the chip first
2145 eHalStatus status = pmcDeferMsg( pMac, eWNI_PMC_WOWL_ADD_BCAST_PTRN,
2146 pattern, sizeof(tSirWowlAddBcastPtrn) );
2147
2148 if( eHAL_STATUS_PMC_PENDING == status )
2149 {
2150 return eHAL_STATUS_SUCCESS;
2151 }
2152 else
2153 {
2154 //either fail or already in full power
2155 if( !HAL_STATUS_SUCCESS( status ) )
2156 {
2157 return ( status );
2158 }
2159 //else let it through because it is in full power state
2160 }
2161 }
2162
2163 if (pmcSendMessage(hHal, eWNI_PMC_WOWL_ADD_BCAST_PTRN, pattern, sizeof(tSirWowlAddBcastPtrn))
2164 != eHAL_STATUS_SUCCESS)
2165 {
2166 smsLog(pMac, LOGE, FL("Send of eWNI_PMC_WOWL_ADD_BCAST_PTRN to PE failed\n"));
2167 return eHAL_STATUS_FAILURE;
2168 }
2169
2170 return eHAL_STATUS_SUCCESS;
2171}
2172
2173/* ---------------------------------------------------------------------------
2174 \fn pmcWowlDelBcastPattern
2175 \brief Delete a pattern that was added for Pattern Byte Matching.
2176 \param hHal - The handle returned by macOpen.
2177 \param pattern - Pattern to be deleted
2178 \return eHalStatus
2179 eHAL_STATUS_FAILURE Cannot delete pattern
2180 eHAL_STATUS_SUCCESS Request accepted.
2181 ---------------------------------------------------------------------------*/
2182eHalStatus pmcWowlDelBcastPattern (
2183 tHalHandle hHal,
2184 tpSirWowlDelBcastPtrn pattern)
2185{
2186 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
2187
2188#ifdef FEATURE_WLAN_DIAG_SUPPORT
2189 WLAN_VOS_DIAG_EVENT_DEF(wowRequest, vos_event_wlan_powersave_wow_payload_type);
2190
2191 vos_mem_zero(&wowRequest, sizeof(vos_event_wlan_powersave_wow_payload_type));
2192 wowRequest.event_subtype = WLAN_WOW_DEL_PTRN_REQ;
2193 wowRequest.wow_del_ptrn_id = pattern->ucPatternId;
2194
2195 WLAN_VOS_DIAG_EVENT_REPORT(&wowRequest, EVENT_WLAN_POWERSAVE_WOW);
2196#endif
2197
2198 smsLog(pMac, LOG2, "PMC: entering pmcWowlDelBcastPattern");
2199
2200 if(pattern->ucPatternId >= SIR_WOWL_BCAST_MAX_NUM_PATTERNS )
2201 {
2202 smsLog(pMac, LOGE, FL("Pattern Id must range from 0 to %d\n"),
2203 SIR_WOWL_BCAST_MAX_NUM_PATTERNS-1);
2204 return eHAL_STATUS_FAILURE;
2205 }
2206
2207 if(pMac->pmc.pmcState == STANDBY || pMac->pmc.pmcState == REQUEST_STANDBY)
2208 {
2209 smsLog(pMac, LOGE, FL("Cannot delete WoWL Pattern as chip is in %s state\n"),
2210 pmcGetPmcStateStr(pMac->pmc.pmcState));
2211 return eHAL_STATUS_FAILURE;
2212 }
2213
2214 if( pMac->pmc.pmcState == IMPS || pMac->pmc.pmcState == REQUEST_IMPS )
2215 {
2216 //Wake up the chip first
2217 eHalStatus status = pmcDeferMsg( pMac, eWNI_PMC_WOWL_DEL_BCAST_PTRN,
2218 pattern, sizeof(tSirWowlDelBcastPtrn) );
2219
2220 if( eHAL_STATUS_PMC_PENDING == status )
2221 {
2222 return eHAL_STATUS_SUCCESS;
2223 }
2224 else
2225 {
2226 //either fail or already in full power
2227 if( !HAL_STATUS_SUCCESS( status ) )
2228 {
2229 return ( status );
2230 }
2231 //else let it through because it is in full power state
2232 }
2233 }
2234
2235 if (pmcSendMessage(hHal, eWNI_PMC_WOWL_DEL_BCAST_PTRN, pattern, sizeof(tSirWowlDelBcastPtrn))
2236 != eHAL_STATUS_SUCCESS)
2237 {
2238 smsLog(pMac, LOGE, FL("Send of eWNI_PMC_WOWL_DEL_BCAST_PTRN to PE failed\n"));
2239 return eHAL_STATUS_FAILURE;
2240 }
2241
2242 return eHAL_STATUS_SUCCESS;
2243}
2244
2245/* ---------------------------------------------------------------------------
2246 \fn pmcEnterWowl
2247 \brief Request that the device be brought to full power state.
2248 Note 1: If "fullPowerReason" specificied in this API is set to
2249 eSME_FULL_PWR_NEEDED_BY_HDD, PMC will clear any "buffered wowl" requests
2250 and also clear any "buffered BMPS requests by HDD". Assumption is that since
2251 HDD is requesting full power, we need to undo any previous HDD requests for
2252 BMPS (using sme_RequestBmps) or WoWL (using sme_EnterWoWL). If the reason is
2253 specified anything other than above, the buffered requests for BMPS and WoWL
2254 will not be cleared.
2255 Note 2: Requesting full power (no matter what the fullPowerReason is) doesn't
2256 disable the "auto bmps timer" (if it is enabled) or clear any "buffered uapsd
2257 request".
2258 Note 3: When the device finally enters Full Power PMC will start a timer
2259 if any of the following holds true:
2260 - Auto BMPS mode is enabled
2261 - Uapsd request is pending
2262 - HDD's request for BMPS is pending
2263 - HDD's request for WoWL is pending
2264 On timer expiry PMC will attempt to put the device in BMPS mode if following
2265 (in addition to those listed above) holds true:
2266 - Polling of all modules through the Power Save Check routine passes
2267 - STA is associated to an access point
2268 \param hHal - The handle returned by macOpen.
2269 \param - enterWowlCallbackRoutine Callback routine invoked in case of success/failure
2270 \param - enterWowlCallbackContext - Cookie to be passed back during callback
2271 \param - wakeReasonIndCB Callback routine invoked for Wake Reason Indication
2272 \param - wakeReasonIndCBContext - Cookie to be passed back during callback
2273 \param - fullPowerReason - Reason why this API is being invoked. SME needs to
2274 distinguish between BAP and HDD requests
2275 \return eHalStatus - status
2276 eHAL_STATUS_SUCCESS - device brought to full power state
2277 eHAL_STATUS_FAILURE - device cannot be brought to full power state
2278 eHAL_STATUS_PMC_PENDING - device is being brought to full power state,
2279 ---------------------------------------------------------------------------*/
2280eHalStatus pmcEnterWowl (
2281 tHalHandle hHal,
2282 void (*enterWowlCallbackRoutine) (void *callbackContext, eHalStatus status),
2283 void *enterWowlCallbackContext,
2284#ifdef WLAN_WAKEUP_EVENTS
2285 void (*wakeReasonIndCB) (void *callbackContext, tpSirWakeReasonInd pWakeReasonInd),
2286 void *wakeReasonIndCBContext,
2287#endif // WLAN_WAKEUP_EVENTS
2288 tpSirSmeWowlEnterParams wowlEnterParams)
2289{
2290 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
2291
2292#ifdef FEATURE_WLAN_DIAG_SUPPORT
2293 WLAN_VOS_DIAG_EVENT_DEF(wowRequest, vos_event_wlan_powersave_wow_payload_type);
2294
2295 vos_mem_zero(&wowRequest, sizeof(vos_event_wlan_powersave_wow_payload_type));
2296 wowRequest.event_subtype = WLAN_WOW_ENTER_REQ;
2297 wowRequest.wow_type = 0;
2298
2299 if(wowlEnterParams->ucMagicPktEnable)
2300 {
2301 wowRequest.wow_type |= 1;
2302 vos_mem_copy(wowRequest.wow_magic_pattern, (tANI_U8 *)wowlEnterParams->magicPtrn, 6);
2303 }
2304
2305 if(wowlEnterParams->ucPatternFilteringEnable)
2306 {
2307 wowRequest.wow_type |= 2;
2308 }
2309
2310 WLAN_VOS_DIAG_EVENT_REPORT(&wowRequest, EVENT_WLAN_POWERSAVE_WOW);
2311#endif
2312
2313 smsLog(pMac, LOG2, "PMC: entering pmcEnterWowl\n");
2314
2315 if( !PMC_IS_READY(pMac) )
2316 {
2317 smsLog(pMac, LOGE, FL("Requesting WoWL when PMC not ready\n"));
2318 smsLog(pMac, LOGE, FL("pmcReady = %d pmcState = %s\n"),
2319 pMac->pmc.pmcReady, pmcGetPmcStateStr(pMac->pmc.pmcState));
2320 return eHAL_STATUS_FAILURE;
2321 }
2322
2323 /* Check if BMPS is enabled. */
2324 if (!pMac->pmc.bmpsEnabled)
2325 {
2326 smsLog(pMac, LOGE, "PMC: Cannot enter WoWL. BMPS is disabled\n");
2327 return eHAL_STATUS_PMC_DISABLED;
2328 }
2329
2330 /* Check if WoWL is enabled. */
2331 if (!pMac->pmc.wowlEnabled)
2332 {
2333 smsLog(pMac, LOGE, "PMC: Cannot enter WoWL. WoWL is disabled\n");
2334 return eHAL_STATUS_PMC_DISABLED;
2335 }
2336
2337 /* Check that we are associated with single Session. */
2338 if (!pmcValidateConnectState( pMac ))
2339 {
2340 smsLog(pMac, LOGE, "PMC: Cannot enable WOWL. STA not associated "
2341 "with an Access Point in Infra Mode with single active session\n");
2342 return eHAL_STATUS_FAILURE;
2343 }
2344
2345 /* Is there a pending UAPSD request? HDD should have triggered QoS
2346 module to do the necessary cleanup before triggring WOWL*/
2347 if(pMac->pmc.uapsdSessionRequired)
2348 {
2349 smsLog(pMac, LOGE, "PMC: Cannot request WOWL. Pending UAPSD request\n");
2350 return eHAL_STATUS_FAILURE;
2351 }
2352
2353 /* Check that entry into a power save mode is allowed at this time. */
2354 if (pMac->pmc.pmcState == FULL_POWER && !pmcPowerSaveCheck(hHal))
2355 {
2356 smsLog(pMac, LOGE, "PMC: Power save check failed. WOWL request "
2357 "will not be accepted\n");
2358 return eHAL_STATUS_FAILURE;
2359 }
2360
2361 // To avoid race condition, set callback routines before sending message.
2362 /* cache the WOWL information */
2363 pMac->pmc.wowlEnterParams = *wowlEnterParams;
2364 pMac->pmc.enterWowlCallbackRoutine = enterWowlCallbackRoutine;
2365 pMac->pmc.enterWowlCallbackContext = enterWowlCallbackContext;
2366#ifdef WLAN_WAKEUP_EVENTS
2367 /* Cache the Wake Reason Indication callback information */
2368 pMac->pmc.wakeReasonIndCB = wakeReasonIndCB;
2369 pMac->pmc.wakeReasonIndCBContext = wakeReasonIndCBContext;
2370#endif // WLAN_WAKEUP_EVENTS
2371
2372 /* Enter Request WOWL State. */
2373 if (pmcRequestEnterWowlState(hHal, wowlEnterParams) != eHAL_STATUS_SUCCESS)
2374 return eHAL_STATUS_FAILURE;
2375
2376 pMac->pmc.wowlModeRequired = TRUE;
2377
2378 return eHAL_STATUS_PMC_PENDING;
2379}
2380
2381/* ---------------------------------------------------------------------------
2382 \fn pmcExitWowl
2383 \brief This is the SME API exposed to HDD to request exit from WoWLAN mode.
2384 SME will initiate exit from WoWLAN mode and device will be put in BMPS
2385 mode.
2386 \param hHal - The handle returned by macOpen.
2387 \return eHalStatus
2388 eHAL_STATUS_FAILURE Device cannot exit WoWLAN mode.
2389 eHAL_STATUS_SUCCESS Request accepted to exit WoWLAN mode.
2390 ---------------------------------------------------------------------------*/
2391eHalStatus pmcExitWowl (tHalHandle hHal)
2392{
2393 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
2394
2395#ifdef FEATURE_WLAN_DIAG_SUPPORT
2396 WLAN_VOS_DIAG_EVENT_DEF(wowRequest, vos_event_wlan_powersave_wow_payload_type);
2397
2398 vos_mem_zero(&wowRequest, sizeof(vos_event_wlan_powersave_wow_payload_type));
2399 wowRequest.event_subtype = WLAN_WOW_EXIT_REQ;
2400
2401 WLAN_VOS_DIAG_EVENT_REPORT(&wowRequest, EVENT_WLAN_POWERSAVE_WOW);
2402#endif
2403
2404 smsLog(pMac, LOG2, "PMC: entering pmcExitWowl");
2405
2406 /* Clear any buffered command for entering WOWL */
2407 pMac->pmc.wowlModeRequired = FALSE;
2408
2409 /* Enter REQUEST_EXIT_WOWL State*/
2410 if (pmcRequestExitWowlState(hHal) != eHAL_STATUS_SUCCESS)
2411 return eHAL_STATUS_FAILURE;
2412
2413 /* Clear the callback routines */
2414 pMac->pmc.enterWowlCallbackRoutine = NULL;
2415 pMac->pmc.enterWowlCallbackContext = NULL;
2416
2417 return eHAL_STATUS_SUCCESS;
2418}
2419
2420
2421
2422/* ---------------------------------------------------------------------------
2423 \fn pmcSetHostOffload
2424 \brief Set the host offload feature.
2425 \param hHal - The handle returned by macOpen.
2426 \param pRequest - Pointer to the offload request.
2427 \return eHalStatus
2428 eHAL_STATUS_FAILURE Cannot set the offload.
2429 eHAL_STATUS_SUCCESS Request accepted.
2430 ---------------------------------------------------------------------------*/
Jeff Johnsone7245742012-09-05 17:12:55 -07002431eHalStatus pmcSetHostOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest, tANI_U8 *bssId)
Jeff Johnson295189b2012-06-20 16:38:30 -07002432{
2433 tpSirHostOffloadReq pRequestBuf;
2434 vos_msg_t msg;
Jeff Johnsone7245742012-09-05 17:12:55 -07002435 tpPESession psessionEntry;
2436 tANI_U8 sessionId;
2437 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
2438
2439 if((psessionEntry = peFindSessionByBssid( pMac, bssId,&sessionId)) == NULL )
2440 {
2441 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Unable to find"
2442 "the psessionEntry for bssid : 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x",
2443 __FUNCTION__,bssId[5],bssId[4],bssId[3],bssId[2],bssId[1],bssId[0]);
2444 return eHAL_STATUS_FAILURE;
2445 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002446
2447 VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: IP address = %d.%d.%d.%d", __FUNCTION__,
2448 pRequest->params.hostIpv4Addr[0], pRequest->params.hostIpv4Addr[1],
2449 pRequest->params.hostIpv4Addr[2], pRequest->params.hostIpv4Addr[3]);
2450
2451 pRequestBuf = vos_mem_malloc(sizeof(tSirHostOffloadReq));
2452 if (NULL == pRequestBuf)
2453 {
2454 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for host offload request", __FUNCTION__);
2455 return eHAL_STATUS_FAILED_ALLOC;
2456 }
2457 vos_mem_copy(pRequestBuf, pRequest, sizeof(tSirHostOffloadReq));
2458
Jeff Johnsone7245742012-09-05 17:12:55 -07002459 pRequestBuf->bssIdx = psessionEntry->bssIdx;
2460
Jeff Johnson295189b2012-06-20 16:38:30 -07002461 msg.type = WDA_SET_HOST_OFFLOAD;
2462 msg.reserved = 0;
2463 msg.bodyptr = pRequestBuf;
2464 if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg))
2465 {
2466 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to post WDA_SET_HOST_OFFLOAD message to WDA", __FUNCTION__);
2467 vos_mem_free(pRequestBuf);
2468 return eHAL_STATUS_FAILURE;
2469 }
2470
2471 return eHAL_STATUS_SUCCESS;
2472}
2473
2474/* ---------------------------------------------------------------------------
2475 \fn pmcSetKeepAlive
2476 \brief Set the Keep Alive feature.
2477 \param hHal - The handle returned by macOpen.
2478 \param pRequest - Pointer to the Keep Alive.
2479 \return eHalStatus
2480 eHAL_STATUS_FAILURE Cannot set the keepalive.
2481 eHAL_STATUS_SUCCESS Request accepted.
2482 ---------------------------------------------------------------------------*/
Jeff Johnsone7245742012-09-05 17:12:55 -07002483eHalStatus pmcSetKeepAlive (tHalHandle hHal, tpSirKeepAliveReq pRequest, tANI_U8 *bssId)
Jeff Johnson295189b2012-06-20 16:38:30 -07002484{
2485 tpSirKeepAliveReq pRequestBuf;
2486 vos_msg_t msg;
Jeff Johnsone7245742012-09-05 17:12:55 -07002487 tpPESession psessionEntry;
2488 tANI_U8 sessionId;
2489 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
2490 if((psessionEntry = peFindSessionByBssid( pMac, bssId,&sessionId)) == NULL )
2491 {
2492 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Unable to find"
2493 "the psessionEntry for bssid : 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x",
2494 __FUNCTION__,bssId[5],bssId[4],bssId[3],bssId[2],bssId[1],bssId[0]);
2495 return eHAL_STATUS_FAILURE;
2496 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002497
2498 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_LOW, "%s: "
2499 "WDA_SET_KEEP_ALIVE message", __FUNCTION__);
2500
2501 pRequestBuf = vos_mem_malloc(sizeof(tSirKeepAliveReq));
2502 if (NULL == pRequestBuf)
2503 {
2504 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: "
2505 "Not able to allocate memory for keep alive request",
2506 __FUNCTION__);
2507 return eHAL_STATUS_FAILED_ALLOC;
2508 }
2509 vos_mem_copy(pRequestBuf, pRequest, sizeof(tSirKeepAliveReq));
Jeff Johnsone7245742012-09-05 17:12:55 -07002510
2511 pRequestBuf->bssIdx = psessionEntry->bssIdx;
2512
Jeff Johnson295189b2012-06-20 16:38:30 -07002513 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_LOW, "buff TP %d "
2514 "input TP %d ", pRequestBuf->timePeriod, pRequest->timePeriod);
2515
2516 msg.type = WDA_SET_KEEP_ALIVE;
2517 msg.reserved = 0;
2518 msg.bodyptr = pRequestBuf;
2519 if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg))
2520 {
2521 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: "
2522 "Not able to post WDA_SET_KEEP_ALIVE message to WDA",
2523 __FUNCTION__);
2524 vos_mem_free(pRequestBuf);
2525 return eHAL_STATUS_FAILURE;
2526 }
2527
2528 return eHAL_STATUS_SUCCESS;
2529}
2530
2531
2532#ifdef WLAN_NS_OFFLOAD
2533
2534/* ---------------------------------------------------------------------------
2535 \fn pmcSetNSOffload
2536 \brief Set the host offload feature.
2537 \param hHal - The handle returned by macOpen.
2538 \param pRequest - Pointer to the offload request.
2539 \return eHalStatus
2540 eHAL_STATUS_FAILURE Cannot set the offload.
2541 eHAL_STATUS_SUCCESS Request accepted.
2542 ---------------------------------------------------------------------------*/
Jeff Johnsone7245742012-09-05 17:12:55 -07002543eHalStatus pmcSetNSOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest, tANI_U8 *bssId)
Jeff Johnson295189b2012-06-20 16:38:30 -07002544{
2545 tpSirHostOffloadReq pRequestBuf;
2546 vos_msg_t msg;
2547 int i;
Jeff Johnsone7245742012-09-05 17:12:55 -07002548 tpPESession psessionEntry;
2549 tANI_U8 sessionId;
2550 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
2551 if((psessionEntry = peFindSessionByBssid( pMac, bssId,&sessionId)) == NULL )
2552 {
2553 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Unable to find"
2554 "the psessionEntry for bssid : 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x",
2555 __FUNCTION__,bssId[5],bssId[4],bssId[3],bssId[2],bssId[1],bssId[0]);
2556 return eHAL_STATUS_FAILURE;
2557 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002558
2559 pRequestBuf = vos_mem_malloc(sizeof(tSirHostOffloadReq));
2560 if (NULL == pRequestBuf)
2561 {
2562 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for NS offload request", __FUNCTION__);
2563 return eHAL_STATUS_FAILED_ALLOC;
2564 }
2565 vos_mem_copy(pRequestBuf, pRequest, sizeof(tSirHostOffloadReq));
2566
Jeff Johnsone7245742012-09-05 17:12:55 -07002567 pRequestBuf->bssIdx = psessionEntry->bssIdx;
2568
Jeff Johnson295189b2012-06-20 16:38:30 -07002569 msg.type = WDA_SET_NS_OFFLOAD;
2570 msg.reserved = 0;
2571 msg.bodyptr = pRequestBuf;
2572 if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg))
2573 {
2574 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to post SIR_HAL_SET_HOST_OFFLOAD message to HAL", __FUNCTION__);
2575 vos_mem_free(pRequestBuf);
2576 return eHAL_STATUS_FAILURE;
2577 }
2578
2579 return eHAL_STATUS_SUCCESS;
2580}
2581
2582#endif //WLAN_NS_OFFLOAD
2583
2584
2585void pmcClosePowerSaveCheckList(tpAniSirGlobal pMac)
2586{
2587 tListElem *pEntry;
2588 tpPowerSaveCheckEntry pPowerSaveCheckEntry;
2589
2590 csrLLLock(&pMac->pmc.powerSaveCheckList);
2591 while ( (pEntry = csrLLRemoveHead(&pMac->pmc.powerSaveCheckList, FALSE)) )
2592 {
2593 pPowerSaveCheckEntry = GET_BASE_ADDR(pEntry, tPowerSaveCheckEntry, link);
2594 if (palFreeMemory(pMac->hHdd, pPowerSaveCheckEntry) != eHAL_STATUS_SUCCESS)
2595 {
2596 smsLog(pMac, LOGE, FL("Cannot free memory \n"));
2597 PMC_ABORT;
2598 break;
2599 }
2600 }
2601 csrLLUnlock(&pMac->pmc.powerSaveCheckList);
2602 csrLLClose(&pMac->pmc.powerSaveCheckList);
2603}
2604
2605
2606void pmcCloseRequestFullPowerList(tpAniSirGlobal pMac)
2607{
2608 tListElem *pEntry;
2609 tpRequestFullPowerEntry pRequestFullPowerEntry;
2610
2611 csrLLLock(&pMac->pmc.requestFullPowerList);
2612 while ( (pEntry = csrLLRemoveHead(&pMac->pmc.requestFullPowerList, FALSE)) )
2613 {
2614 pRequestFullPowerEntry = GET_BASE_ADDR(pEntry, tRequestFullPowerEntry, link);
2615 if (palFreeMemory(pMac->hHdd, pRequestFullPowerEntry) != eHAL_STATUS_SUCCESS)
2616 {
2617 smsLog(pMac, LOGE, FL("Cannot free memory \n"));
2618 PMC_ABORT;
2619 break;
2620 }
2621 }
2622 csrLLUnlock(&pMac->pmc.requestFullPowerList);
2623 csrLLClose(&pMac->pmc.requestFullPowerList);
2624}
2625
2626
2627void pmcCloseRequestBmpsList(tpAniSirGlobal pMac)
2628{
2629 tListElem *pEntry;
2630 tpRequestBmpsEntry pRequestBmpsEntry;
2631
2632 csrLLLock(&pMac->pmc.requestBmpsList);
2633 while ( (pEntry = csrLLRemoveHead(&pMac->pmc.requestBmpsList, FALSE)) )
2634 {
2635 pRequestBmpsEntry = GET_BASE_ADDR(pEntry, tRequestBmpsEntry, link);
2636 if (palFreeMemory(pMac->hHdd, pRequestBmpsEntry) != eHAL_STATUS_SUCCESS)
2637 {
2638 smsLog(pMac, LOGE, FL("Cannot free memory \n"));
2639 PMC_ABORT;
2640 break;
2641 }
2642 }
2643 csrLLUnlock(&pMac->pmc.requestBmpsList);
2644 csrLLClose(&pMac->pmc.requestBmpsList);
2645}
2646
2647
2648void pmcCloseRequestStartUapsdList(tpAniSirGlobal pMac)
2649{
2650 tListElem *pEntry;
2651 tpStartUapsdEntry pStartUapsdEntry;
2652
2653 csrLLLock(&pMac->pmc.requestStartUapsdList);
2654 while ( (pEntry = csrLLRemoveHead(&pMac->pmc.requestStartUapsdList, FALSE)) )
2655 {
2656 pStartUapsdEntry = GET_BASE_ADDR(pEntry, tStartUapsdEntry, link);
2657 if (palFreeMemory(pMac->hHdd, pStartUapsdEntry) != eHAL_STATUS_SUCCESS)
2658 {
2659 smsLog(pMac, LOGE, FL("Cannot free memory \n"));
2660 PMC_ABORT;
2661 break;
2662 }
2663 }
2664 csrLLUnlock(&pMac->pmc.requestStartUapsdList);
2665 csrLLClose(&pMac->pmc.requestStartUapsdList);
2666}
2667
2668
2669void pmcCloseDeviceStateUpdateList(tpAniSirGlobal pMac)
2670{
2671 tListElem *pEntry;
2672 tpDeviceStateUpdateIndEntry pDeviceStateUpdateIndEntry;
2673
2674 csrLLLock(&pMac->pmc.deviceStateUpdateIndList);
2675 while ( (pEntry = csrLLRemoveHead(&pMac->pmc.deviceStateUpdateIndList, FALSE)) )
2676 {
2677 pDeviceStateUpdateIndEntry = GET_BASE_ADDR(pEntry, tDeviceStateUpdateIndEntry, link);
2678 if (palFreeMemory(pMac->hHdd, pDeviceStateUpdateIndEntry) != eHAL_STATUS_SUCCESS)
2679 {
2680 smsLog(pMac, LOGE, FL("Cannot free memory \n"));
2681 PMC_ABORT;
2682 break;
2683 }
2684 }
2685 csrLLUnlock(&pMac->pmc.deviceStateUpdateIndList);
2686 csrLLClose(&pMac->pmc.deviceStateUpdateIndList);
2687}
2688
2689
2690void pmcCloseDeferredMsgList(tpAniSirGlobal pMac)
2691{
2692 tListElem *pEntry;
2693 tPmcDeferredMsg *pDeferredMsg;
2694
2695 csrLLLock(&pMac->pmc.deferredMsgList);
2696 while ( (pEntry = csrLLRemoveHead(&pMac->pmc.deferredMsgList, FALSE)) )
2697 {
2698 pDeferredMsg = GET_BASE_ADDR(pEntry, tPmcDeferredMsg, link);
2699 if (palFreeMemory(pMac->hHdd, pDeferredMsg) != eHAL_STATUS_SUCCESS)
2700 {
2701 smsLog(pMac, LOGE, FL("Cannot free memory \n"));
2702 PMC_ABORT;
2703 break;
2704 }
2705 }
2706 csrLLUnlock(&pMac->pmc.deferredMsgList);
2707 csrLLClose(&pMac->pmc.deferredMsgList);
2708}
2709
2710
2711#ifdef FEATURE_WLAN_SCAN_PNO
2712
2713static tSirRetStatus
2714pmcPopulateMacHeader( tpAniSirGlobal pMac,
2715 tANI_U8* pBD,
2716 tANI_U8 type,
2717 tANI_U8 subType,
2718 tSirMacAddr peerAddr ,
2719 tSirMacAddr selfMacAddr)
2720{
2721 tSirRetStatus statusCode = eSIR_SUCCESS;
2722 tpSirMacMgmtHdr pMacHdr;
2723
2724 /// Prepare MAC management header
2725 pMacHdr = (tpSirMacMgmtHdr) (pBD);
2726
2727 // Prepare FC
2728 pMacHdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION;
2729 pMacHdr->fc.type = type;
2730 pMacHdr->fc.subType = subType;
2731
2732 // Prepare Address 1
2733 palCopyMemory( pMac->hHdd,
2734 (tANI_U8 *) pMacHdr->da,
2735 (tANI_U8 *) peerAddr,
2736 sizeof( tSirMacAddr ));
2737
2738 sirCopyMacAddr(pMacHdr->sa,selfMacAddr);
2739
2740 // Prepare Address 3
2741 palCopyMemory( pMac->hHdd,
2742 (tANI_U8 *) pMacHdr->bssId,
2743 (tANI_U8 *) peerAddr,
2744 sizeof( tSirMacAddr ));
2745 return statusCode;
2746} /*** pmcPopulateMacHeader() ***/
2747
2748
2749static tSirRetStatus
2750pmcPrepareProbeReqTemplate(tpAniSirGlobal pMac,
2751 tANI_U8 nChannelNum,
2752 tANI_U32 dot11mode,
2753 tSirMacAddr selfMacAddr,
2754 tANI_U8 *pFrame,
2755 tANI_U16 *pusLen)
2756{
2757 tDot11fProbeRequest pr;
2758 tANI_U32 nStatus, nBytes, nPayload;
2759 tSirRetStatus nSirStatus;
2760 /*Bcast tx*/
2761 tSirMacAddr bssId = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
2762 /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2763
2764 // The scheme here is to fill out a 'tDot11fProbeRequest' structure
2765 // and then hand it off to 'dot11fPackProbeRequest' (for
2766 // serialization). We start by zero-initializing the structure:
2767 palZeroMemory( pMac->hHdd, ( tANI_U8* )&pr, sizeof( pr ) );
2768
2769 PopulateDot11fSuppRates( pMac, nChannelNum, &pr.SuppRates,NULL);
2770
2771 if ( WNI_CFG_DOT11_MODE_11B != dot11mode )
2772 {
2773 PopulateDot11fExtSuppRates1( pMac, nChannelNum, &pr.ExtSuppRates );
2774 }
2775
2776
2777 if (IS_DOT11_MODE_HT(dot11mode))
2778 {
Jeff Johnsone7245742012-09-05 17:12:55 -07002779 PopulateDot11fHTCaps( pMac, NULL, &pr.HTCaps );
Jeff Johnson295189b2012-06-20 16:38:30 -07002780 }
2781
2782 // That's it-- now we pack it. First, how much space are we going to
2783 // need?
2784 nStatus = dot11fGetPackedProbeRequestSize( pMac, &pr, &nPayload );
2785 if ( DOT11F_FAILED( nStatus ) )
2786 {
2787 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2788 "Failed to calculate the packed size f"
2789 "or a Probe Request (0x%08x).\n", nStatus );
2790
2791 // We'll fall back on the worst case scenario:
2792 nPayload = sizeof( tDot11fProbeRequest );
2793 }
2794 else if ( DOT11F_WARNED( nStatus ) )
2795 {
2796 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2797 "There were warnings while calculating"
2798 "the packed size for a Probe Request ("
2799 "0x%08x).\n", nStatus );
2800 }
2801
2802 nBytes = nPayload + sizeof( tSirMacMgmtHdr );
2803
2804 /* Prepare outgoing frame*/
2805 palZeroMemory( pMac->hHdd, pFrame, nBytes );
2806
2807 // Next, we fill out the buffer descriptor:
2808 nSirStatus = pmcPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME,
2809 SIR_MAC_MGMT_PROBE_REQ, bssId ,selfMacAddr);
2810
2811 if ( eSIR_SUCCESS != nSirStatus )
2812 {
2813 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2814 "Failed to populate the buffer descriptor for a Probe Request (%d).\n",
2815 nSirStatus );
2816 return nSirStatus; // allocated!
2817 }
2818
2819 // That done, pack the Probe Request:
2820 nStatus = dot11fPackProbeRequest( pMac, &pr, pFrame +
2821 sizeof( tSirMacMgmtHdr ),
2822 nPayload, &nPayload );
2823 if ( DOT11F_FAILED( nStatus ) )
2824 {
2825 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2826 "Failed to pack a Probe Request (0x%08x).\n", nStatus );
2827 return eSIR_FAILURE; // allocated!
2828 }
2829 else if ( DOT11F_WARNED( nStatus ) )
2830 {
2831 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
2832 "There were warnings while packing a Probe Request (0x%08x).\n" );
2833 }
2834
2835 *pusLen = nPayload + sizeof(tSirMacMgmtHdr);
2836 return eSIR_SUCCESS;
2837} // End pmcPrepareProbeReqTemplate.
2838
2839
2840eHalStatus pmcSetPreferredNetworkList
2841(
2842 tHalHandle hHal,
2843 tpSirPNOScanReq pRequest,
2844 tANI_U8 sessionId,
2845 preferredNetworkFoundIndCallback callbackRoutine,
2846 void *callbackContext
2847)
2848{
2849 tpSirPNOScanReq pRequestBuf;
2850 vos_msg_t msg;
2851 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
2852 tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
2853 tANI_U8 ucDot11Mode;
2854
2855 VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: SSID = %s, %s", __FUNCTION__,
2856 pRequest->aNetworks[0].ssId.ssId, pRequest->aNetworks[1].ssId.ssId);
2857
2858 pRequestBuf = vos_mem_malloc(sizeof(tSirPNOScanReq));
2859 if (NULL == pRequestBuf)
2860 {
2861 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for PNO request", __FUNCTION__);
2862 return eHAL_STATUS_FAILED_ALLOC;
2863 }
2864
2865 vos_mem_copy(pRequestBuf, pRequest, sizeof(tSirPNOScanReq));
2866
2867 /*Must translate the mode first*/
2868 ucDot11Mode = (tANI_U8) csrTranslateToWNICfgDot11Mode(pMac,
2869 csrFindBestPhyMode( pMac, pMac->roam.configParam.phyMode ));
2870
2871 /*Prepare a probe request for 2.4GHz band and one for 5GHz band*/
2872 pmcPrepareProbeReqTemplate(pMac,SIR_PNO_24G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr,
2873 pRequestBuf->p24GProbeTemplate, &pRequestBuf->us24GProbeTemplateLen);
2874
2875 pmcPrepareProbeReqTemplate(pMac,SIR_PNO_5G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr,
2876 pRequestBuf->p5GProbeTemplate, &pRequestBuf->us5GProbeTemplateLen);
2877
2878
2879 msg.type = WDA_SET_PNO_REQ;
2880 msg.reserved = 0;
2881 msg.bodyptr = pRequestBuf;
2882 if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)))
2883 {
2884 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to post WDA_SET_PNO_REQ message to WDA", __FUNCTION__);
2885 vos_mem_free(pRequestBuf);
2886 return eHAL_STATUS_FAILURE;
2887 }
2888
2889 /* Cache the Preferred Network Found Indication callback information */
2890 pMac->pmc.prefNetwFoundCB = callbackRoutine;
2891 pMac->pmc.preferredNetworkFoundIndCallbackContext = callbackContext;
2892
2893 VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "-%s", __FUNCTION__);
2894
2895 return eHAL_STATUS_SUCCESS;
2896}
2897
2898eHalStatus pmcSetRssiFilter(tHalHandle hHal, v_U8_t rssiThreshold)
2899{
2900 tpSirSetRSSIFilterReq pRequestBuf;
2901 vos_msg_t msg;
2902
2903
2904 pRequestBuf = vos_mem_malloc(sizeof(tpSirSetRSSIFilterReq));
2905 if (NULL == pRequestBuf)
2906 {
2907 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for PNO request", __FUNCTION__);
2908 return eHAL_STATUS_FAILED_ALLOC;
2909 }
2910
2911
2912 pRequestBuf->rssiThreshold = rssiThreshold;
2913
2914 msg.type = WDA_SET_RSSI_FILTER_REQ;
2915 msg.reserved = 0;
2916 msg.bodyptr = pRequestBuf;
2917 if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)))
2918 {
2919 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to post WDA_SET_PNO_REQ message to WDA", __FUNCTION__);
2920 vos_mem_free(pRequestBuf);
2921 return eHAL_STATUS_FAILURE;
2922 }
2923
2924 return eHAL_STATUS_SUCCESS;
2925}
2926
2927
2928eHalStatus pmcUpdateScanParams(tHalHandle hHal, tCsrConfig *pRequest, tCsrChannel *pChannelList, tANI_U8 b11dResolved)
2929{
2930 tpSirUpdateScanParams pRequestBuf;
2931 vos_msg_t msg;
2932 int i;
2933
2934 VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s started", __FUNCTION__);
2935
2936 pRequestBuf = vos_mem_malloc(sizeof(tSirUpdateScanParams));
2937 if (NULL == pRequestBuf)
2938 {
2939 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for UpdateScanParams request", __FUNCTION__);
2940 return eHAL_STATUS_FAILED_ALLOC;
2941 }
2942
2943 //
2944 // Fill pRequestBuf structure from pRequest
2945 //
2946 pRequestBuf->b11dEnabled = pRequest->Is11eSupportEnabled;
2947 pRequestBuf->b11dResolved = b11dResolved;
2948 pRequestBuf->ucChannelCount =
2949 ( pChannelList->numChannels < SIR_PNO_MAX_NETW_CHANNELS )?
2950 pChannelList->numChannels:SIR_PNO_MAX_NETW_CHANNELS;
2951
2952 for (i=0; i < pChannelList->numChannels; i++)
2953 {
2954 pRequestBuf->aChannels[i] = pChannelList->channelList[i];
2955 }
2956 pRequestBuf->usPassiveMinChTime = pRequest->nPassiveMinChnTime;
2957 pRequestBuf->usPassiveMaxChTime = pRequest->nPassiveMaxChnTime;
2958 pRequestBuf->usActiveMinChTime = pRequest->nActiveMinChnTime;
2959 pRequestBuf->usActiveMaxChTime = pRequest->nActiveMaxChnTime;
2960 pRequestBuf->ucCBState = PHY_SINGLE_CHANNEL_CENTERED;
2961
2962 msg.type = WDA_UPDATE_SCAN_PARAMS_REQ;
2963 msg.reserved = 0;
2964 msg.bodyptr = pRequestBuf;
2965 if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)))
2966 {
2967 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to post WDA_UPDATE_SCAN_PARAMS message to WDA", __FUNCTION__);
2968 vos_mem_free(pRequestBuf);
2969 return eHAL_STATUS_FAILURE;
2970 }
2971
2972 return eHAL_STATUS_SUCCESS;
2973}
2974#endif // FEATURE_WLAN_SCAN_PNO
2975
2976eHalStatus pmcSetPowerParams(tHalHandle hHal, tSirSetPowerParamsReq* pwParams)
2977{
2978 tSirSetPowerParamsReq* pRequestBuf;
2979 vos_msg_t msg;
2980 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
2981 tpPESession psessionEntry;
2982
2983 if((psessionEntry = peGetValidPowerSaveSession(pMac))== NULL)
2984 {
2985 return eHAL_STATUS_NOT_INITIALIZED;
2986 }
2987
2988 pRequestBuf = vos_mem_malloc(sizeof(tSirSetPowerParamsReq));
2989 if (NULL == pRequestBuf)
2990 {
2991 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for Power Paramrequest", __FUNCTION__);
2992 return eHAL_STATUS_FAILED_ALLOC;
2993 }
2994
2995
2996 vos_mem_copy(pRequestBuf, pwParams, sizeof(*pRequestBuf));
2997
2998
2999 msg.type = WDA_SET_POWER_PARAMS_REQ;
3000 msg.reserved = 0;
3001 msg.bodyptr = pRequestBuf;
3002
3003 if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg))
3004 {
3005 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to post WDA_SET_POWER_PARAMS_REQ message to WDA", __FUNCTION__);
3006 vos_mem_free(pRequestBuf);
3007 return eHAL_STATUS_FAILURE;
3008 }
3009
3010 return eHAL_STATUS_SUCCESS;
3011}
3012
3013#ifdef WLAN_FEATURE_PACKET_FILTERING
3014eHalStatus pmcGetFilterMatchCount
3015(
3016 tHalHandle hHal,
3017 FilterMatchCountCallback callbackRoutine,
3018 void *callbackContext
3019)
3020{
3021 tpSirRcvFltPktMatchRsp pRequestBuf;
3022 vos_msg_t msg;
3023 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
3024
3025 VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
3026 "%s: filterId = %d", __FUNCTION__);
3027
3028 pRequestBuf = vos_mem_malloc(sizeof(tSirRcvFltPktMatchRsp));
3029 if (NULL == pRequestBuf)
3030 {
3031 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
3032 "%s: Not able to allocate "
3033 "memory for Get PC Filter Match Count request", __FUNCTION__);
3034 return eHAL_STATUS_FAILED_ALLOC;
3035 }
3036
3037 msg.type = WDA_PACKET_COALESCING_FILTER_MATCH_COUNT_REQ;
3038 msg.reserved = 0;
3039 msg.bodyptr = pRequestBuf;
3040
3041 /* Cache the Packet Coalescing Filter Match Count callback information */
3042 if (NULL != pMac->pmc.FilterMatchCountCB)
3043 {
3044 // Do we need to check if the callback is in use?
3045 // Because we are not sending the same message again when it is pending,
3046 // the only case when the callback is not NULL is that the previous message
3047 //was timed out or failed.
3048 // So, it will be safe to set the callback in this case.
3049 }
3050
3051 pMac->pmc.FilterMatchCountCB = callbackRoutine;
3052 pMac->pmc.FilterMatchCountCBContext = callbackContext;
3053
3054 if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg))
3055 {
3056 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
3057 "%s: Not able to post WDA_PACKET_COALESCING_FILTER_MATCH_COUNT_REQ "
3058 "message to WDA", __FUNCTION__);
3059 return eHAL_STATUS_FAILURE;
3060 }
3061
3062 return eHAL_STATUS_SUCCESS;
3063}
3064#endif // WLAN_FEATURE_PACKET_FILTERING
3065
3066#ifdef WLAN_FEATURE_GTK_OFFLOAD
3067/* ---------------------------------------------------------------------------
3068 \fn pmcSetGTKOffload
3069 \brief Set GTK offload feature.
3070 \param hHal - The handle returned by macOpen.
3071 \param pGtkOffload - Pointer to the GTK offload request.
3072 \return eHalStatus
3073 eHAL_STATUS_FAILURE Cannot set the offload.
3074 eHAL_STATUS_SUCCESS Request accepted.
3075 ---------------------------------------------------------------------------*/
3076eHalStatus pmcSetGTKOffload (tHalHandle hHal, tpSirGtkOffloadParams pGtkOffload)
3077{
3078 tpSirGtkOffloadParams pRequestBuf;
3079 vos_msg_t msg;
3080 int i;
3081
3082 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: KeyReplayCounter: %d",
3083 __FUNCTION__, pGtkOffload->ullKeyReplayCounter);
3084
3085 pRequestBuf = (tpSirGtkOffloadParams)vos_mem_malloc(sizeof(tSirGtkOffloadParams));
3086 if (NULL == pRequestBuf)
3087 {
3088 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate "
3089 "memory for GTK offload request", __FUNCTION__);
3090 return eHAL_STATUS_FAILED_ALLOC;
3091 }
3092
3093 vos_mem_copy(pRequestBuf, pGtkOffload, sizeof(tSirGtkOffloadParams));
3094
3095 msg.type = WDA_GTK_OFFLOAD_REQ;
3096 msg.reserved = 0;
3097 msg.bodyptr = pRequestBuf;
3098 if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)))
3099 {
3100 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to post "
3101 "SIR_HAL_SET_GTK_OFFLOAD message to HAL", __FUNCTION__);
3102 vos_mem_free(pRequestBuf);
3103 return eHAL_STATUS_FAILURE;
3104 }
3105
3106 return eHAL_STATUS_SUCCESS;
3107}
3108
3109/* ---------------------------------------------------------------------------
3110 \fn pmcGetGTKOffload
3111 \brief Get GTK offload information.
3112 \param hHal - The handle returned by macOpen.
3113 \param callbackRoutine - Pointer to the GTK Offload Get Info response callback routine.
3114 \return eHalStatus
3115 eHAL_STATUS_FAILURE Cannot set the offload.
3116 eHAL_STATUS_SUCCESS Request accepted.
3117 ---------------------------------------------------------------------------*/
3118eHalStatus pmcGetGTKOffload(tHalHandle hHal, GTKOffloadGetInfoCallback callbackRoutine, void *callbackContext)
3119{
3120 tpSirGtkOffloadGetInfoRspParams pRequestBuf;
3121 vos_msg_t msg;
3122 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
3123
3124 VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: filterId = %d",
3125 __FUNCTION__);
3126
3127 pRequestBuf = vos_mem_malloc(sizeof(tSirGtkOffloadGetInfoRspParams));
3128 if (NULL == pRequestBuf)
3129 {
3130 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate "
3131 "memory for Get GTK Offload request", __FUNCTION__);
3132 return eHAL_STATUS_FAILED_ALLOC;
3133 }
3134
3135 msg.type = WDA_GTK_OFFLOAD_GETINFO_REQ;
3136 msg.reserved = 0;
3137 msg.bodyptr = pRequestBuf;
3138
3139 /* Cache the Get GTK Offload callback information */
3140 if (NULL != pMac->pmc.GtkOffloadGetInfoCB)
3141 {
3142 // Do we need to check if the callback is in use?
3143 // Because we are not sending the same message again when it is pending,
3144 // the only case when the callback is not NULL is that the previous message was timed out or failed.
3145 // So, it will be safe to set the callback in this case.
3146 }
3147
3148 pMac->pmc.GtkOffloadGetInfoCB = callbackRoutine;
3149 pMac->pmc.GtkOffloadGetInfoCBContext = callbackContext;
3150
3151 if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)))
3152 {
3153 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to post WDA_GTK_OFFLOAD_GETINFO_REQ message to WDA",
3154 __FUNCTION__);
3155 vos_mem_free(pRequestBuf);
3156 return eHAL_STATUS_FAILURE;
3157 }
3158
3159 return eHAL_STATUS_SUCCESS;
3160}
3161#endif // WLAN_FEATURE_GTK_OFFLOAD